Codebase list python-pyproj / ffd25ee
New upstream version 2.3.1+ds Bas Couwenberg 4 years ago
14 changed file(s) with 301 addition(s) and 216 deletion(s). Raw diff Collapse all Expand all
4646 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
4747 NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
4848 CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. """
49 __version__ = "2.3.0"
49 __version__ = "2.3.1"
5050 __all__ = [
5151 "Proj",
5252 "Geod",
6565 ]
6666 import sys
6767
68 from pyproj._datadir import PYPROJ_CONTEXT
6869 from pyproj._list import ( # noqa: F401
6970 get_angular_units_map,
7071 get_ellps_map,
7879 from pyproj.geod import Geod, geodesic_version_str, pj_ellps # noqa: F401
7980 from pyproj.proj import Proj, pj_list, proj_version_str # noqa: F401
8081 from pyproj.transformer import Transformer, itransform, transform # noqa: F401
82
83 PYPROJ_CONTEXT.set_search_paths()
8184
8285
8386 def test(**kwargs):
9090 PROJ_CONTEXT.context,
9191 projobj,
9292 wkt_out_type,
93 options_wkt)
93 options_wkt,
94 )
95 CRSError.clear()
9496 return cstrdecode(proj_string)
9597
9698
121123 PROJ_CONTEXT.context,
122124 projobj,
123125 proj_out_type,
124 NULL)
126 NULL,
127 )
128 CRSError.clear()
125129 return cstrdecode(proj_string)
126130
127131
128132 cdef PJ* _from_authority(
129133 auth_name, code, PJ_CATEGORY category, int use_proj_alternative_grid_names=False
130134 ):
131 CRSError.clear()
132135 b_auth_name = cstrencode(auth_name)
133136 cdef char *c_auth_name = b_auth_name
134137 b_code = cstrencode(str(code))
144147
145148
146149 cdef PJ* _from_string(proj_string, expected_types):
147 CRSError.clear()
148150 cdef PJ* base_pj = proj_create(
149151 PROJ_CONTEXT.context,
150152 cstrencode(proj_string)
403405 coord_system.name = _COORD_SYSTEM_TYPE_MAP[cs_type]
404406 except KeyError:
405407 raise CRSError("Not a coordinate system.")
408 CRSError.clear()
406409 return coord_system
407410
408411 @property
457460 cdef Ellipsoid ellips = Ellipsoid()
458461 ellips.projobj = ellipsoid_pj
459462 cdef int is_semi_minor_computed = 0
460 try:
461 proj_ellipsoid_get_parameters(
462 PROJ_CONTEXT.context,
463 ellips.projobj,
464 &ellips._semi_major_metre,
465 &ellips._semi_minor_metre,
466 &is_semi_minor_computed,
467 &ellips._inv_flattening)
468 ellips.ellipsoid_loaded = True
469 ellips.is_semi_minor_computed = is_semi_minor_computed == 1
470 except Exception:
471 pass
463 proj_ellipsoid_get_parameters(
464 PROJ_CONTEXT.context,
465 ellips.projobj,
466 &ellips._semi_major_metre,
467 &ellips._semi_minor_metre,
468 &is_semi_minor_computed,
469 &ellips._inv_flattening,
470 )
471 ellips.ellipsoid_loaded = True
472 ellips.is_semi_minor_computed = is_semi_minor_computed == 1
472473 ellips._set_name()
474 CRSError.clear()
473475 return ellips
474476
475477 @staticmethod
497499 raise CRSError(
498500 "Invalid authority or code ({0}, {1})".format(auth_name, code)
499501 )
502 CRSError.clear()
500503 return Ellipsoid.create(ellipsoid_pj)
501504
502505 @staticmethod
545548 pystrdecode(ellipsoid_string)
546549 )
547550 )
548
551 CRSError.clear()
549552 return Ellipsoid.create(ellipsoid_pj)
550553
551554 @property
619622 )
620623 prime_meridian.unit_name = decode_or_undefined(unit_name)
621624 prime_meridian._set_name()
625 CRSError.clear()
622626 return prime_meridian
623627
624628 @staticmethod
646650 raise CRSError(
647651 "Invalid authority or code ({0}, {1})".format(auth_name, code)
648652 )
653 CRSError.clear()
649654 return PrimeMeridian.create(prime_meridian_pj)
650655
651656 @staticmethod
663668 PrimeMeridian
664669 """
665670 return PrimeMeridian.from_authority("EPSG", code)
666
667671
668672 @staticmethod
669673 def from_string(prime_meridian_string):
695699 pystrdecode(prime_meridian_string)
696700 )
697701 )
698
702 CRSError.clear()
699703 return PrimeMeridian.create(prime_meridian_pj)
700704
701705
745749 raise CRSError(
746750 "Invalid authority or code ({0}, {1})".format(auth_name, code)
747751 )
752 CRSError.clear()
748753 return Datum.create(datum_pj)
749754
750755 @staticmethod
800805 pystrdecode(datum_string)
801806 )
802807 )
803
808 CRSError.clear()
804809 return Datum.create(datum_pj)
805810
806811 @property
816821 PROJ_CONTEXT.context,
817822 self.projobj,
818823 )
824 CRSError.clear()
819825 if ellipsoid_pj == NULL:
820826 self._ellipsoid = False
821827 return None
835841 PROJ_CONTEXT.context,
836842 self.projobj,
837843 )
844 CRSError.clear()
838845 if prime_meridian_pj == NULL:
839846 self._prime_meridian = False
840847 return None
9981005 grid.direct_download = direct_download == 1
9991006 grid.open_license = open_license == 1
10001007 grid.available = available == 1
1008 CRSError.clear()
10011009 return grid
10021010
10031011 def __str__(self):
10841092 PROJ_CONTEXT.context,
10851093 coord_operation.projobj
10861094 ) == 1
1087
1095 CRSError.clear()
10881096 return coord_operation
10891097
10901098 @staticmethod
11151123 raise CRSError(
11161124 "Invalid authority or code ({0}, {1})".format(auth_name, code)
11171125 )
1126 CRSError.clear()
11181127 return CoordinateOperation.create(coord_operation_pj)
11191128
11201129 @staticmethod
11691178 pystrdecode(coordinate_operation_string)
11701179 )
11711180 )
1172
1181 CRSError.clear()
11731182 return CoordinateOperation.create(coord_operation_pj)
11741183
11751184 @property
11941203 param_idx
11951204 )
11961205 )
1206 CRSError.clear()
11971207 return self._params
11981208
11991209 @property
12181228 grid_idx
12191229 )
12201230 )
1231 CRSError.clear()
12211232 return self._grids
12221233
12231234 @property
13301341 self._type = proj_get_type(self.projobj)
13311342 self.type_name = _CRS_TYPE_MAP[self._type]
13321343 self._set_name()
1344 CRSError.clear()
13331345
13341346 @property
13351347 def axis_info(self):
13651377 PROJ_CONTEXT.context,
13661378 self.projobj
13671379 )
1380 CRSError.clear()
13681381 if ellipsoid_pj == NULL:
13691382 self._ellipsoid = False
13701383 return None
13841397 PROJ_CONTEXT.context,
13851398 self.projobj,
13861399 )
1400 CRSError.clear()
13871401 if prime_meridian_pj == NULL:
13881402 self._prime_meridian = False
13891403 return None
14051419 PROJ_CONTEXT.context,
14061420 self.projobj,
14071421 )
1422 CRSError.clear()
14081423 if datum_pj == NULL:
14091424 self._datum = False
14101425 return None
14251440 PROJ_CONTEXT.context,
14261441 self.projobj
14271442 )
1443 CRSError.clear()
14281444 if coord_system_pj == NULL:
14291445 self._coordinate_system = False
14301446 return None
14461462 PROJ_CONTEXT.context,
14471463 self.projobj
14481464 )
1465 CRSError.clear()
14491466 if coord_pj == NULL:
14501467 self._coordinate_operation = False
14511468 return None
14641481 return None if self._source_crs is False else self._source_crs
14651482 cdef PJ * projobj
14661483 projobj = proj_get_source_crs(PROJ_CONTEXT.context, self.projobj)
1484 CRSError.clear()
14671485 if projobj == NULL:
14681486 self._source_crs = False
14691487 return None
14841502 return None if self._target_crs is False else self._target_crs
14851503 cdef PJ * projobj
14861504 projobj = proj_get_target_crs(PROJ_CONTEXT.context, self.projobj)
1505 CRSError.clear()
14871506 if projobj == NULL:
14881507 self._target_crs = False
14891508 return None
15181537 proj_destroy(projobj) # deallocate temp proj
15191538 iii += 1
15201539 projobj = proj_crs_get_sub_crs(PROJ_CONTEXT.context, self.projobj, iii)
1521
1540 CRSError.clear()
15221541 return self._sub_crs_list
15231542
15241543 @property
15321551 return self._geodetic_crs if self. _geodetic_crs is not False else None
15331552 cdef PJ * projobj
15341553 projobj = proj_crs_get_geodetic_crs(PROJ_CONTEXT.context, self.projobj)
1554 CRSError.clear()
15351555 if projobj == NULL:
15361556 self._geodetic_crs = False
15371557 return None
16031623 if auth_info is not None and auth_info[0].upper() == "EPSG":
16041624 return int(auth_info[1])
16051625 return None
1606
1626
16071627 def to_authority(self, auth_name=None, min_confidence=70):
16081628 """
16091629 Return the authority name and code best matching the CRS
16661686 finally:
16671687 if out_confidence_list != NULL:
16681688 proj_int_list_destroy(out_confidence_list)
1689 CRSError.clear()
16691690
16701691 # check to make sure that the projection found is valid
16711692 if proj_list == NULL or num_proj_objects <= 0 or out_confidence < min_confidence:
16791700 proj = proj_list_get(PROJ_CONTEXT.context, proj_list, 0)
16801701 finally:
16811702 proj_list_destroy(proj_list)
1703 CRSError.clear()
16821704 if proj == NULL:
16831705 return None
16841706
16921714 return pystrdecode(out_auth_name), pystrdecode(code)
16931715 finally:
16941716 proj_destroy(proj)
1717 CRSError.clear()
16951718
16961719 return None
16971720
17271750 is_property = self._type in property_types
17281751 return is_property
17291752
1730
17311753 @property
17321754 def is_geographic(self):
17331755 """
33
44 cdef class ContextManager:
55 cdef PJ_CONTEXT *context
6 cdef object _set_search_paths
1212 if level == PJ_LOG_ERROR:
1313 ProjError.internal_proj_error = pystrdecode(error_msg)
1414
15
1615 cdef class ContextManager:
1716 def __cinit__(self):
1817 self.context = NULL
2423
2524 def __init__(self):
2625 self.context = proj_context_create()
27 self.set_search_paths()
26 self._set_search_paths = False
2827 proj_context_use_proj4_init_rules(self.context, 1)
2928 proj_log_func(self.context, NULL, pyproj_log_function)
3029
31 def set_search_paths(self):
30 def set_search_paths(self, reset=False):
3231 """
3332 This method sets the search paths
3433 based on pyproj.datadir.get_data_dir()
3534 """
35 if self._set_search_paths and not reset:
36 return
3637 data_dir_list = get_data_dir().split(os.pathsep)
3738 cdef char **c_data_dir = <char **>malloc(len(data_dir_list) * sizeof(char*))
3839 try:
3940 for iii in range(len(data_dir_list)):
4041 b_data_dir = cstrencode(data_dir_list[iii])
4142 c_data_dir[iii] = b_data_dir
43 proj_context_set_search_paths(NULL, len(data_dir_list), c_data_dir)
4244 proj_context_set_search_paths(self.context, len(data_dir_list), c_data_dir)
4345 finally:
4446 free(c_data_dir)
47 self._set_search_paths = True
4548
4649
4750 cdef ContextManager PROJ_CONTEXT = ContextManager()
00 include "proj.pxi"
11
22 cdef class Proj:
3 cdef PJ * projpj
4 cdef PJ_PROJ_INFO projpj_info
3 cdef PJ * projobj
4 cdef PJ_PROJ_INFO projobj_info
55 cdef readonly srs
1717
1818 cdef class Proj:
1919 def __cinit__(self):
20 self.projpj = NULL
20 self.projobj = NULL
2121
2222 def __init__(self, const char *projstring):
2323 self.srs = pystrdecode(projstring)
2424 # initialize projection
25 self.projpj = proj_create(PROJ_CONTEXT.context, projstring)
26 if self.projpj is NULL:
25 self.projobj = proj_create(PROJ_CONTEXT.context, projstring)
26 if self.projobj is NULL:
2727 raise ProjError("Invalid projection {}.".format(projstring))
28 self.projpj_info = proj_pj_info(self.projpj)
28 self.projobj_info = proj_pj_info(self.projobj)
29 ProjError.clear()
2930
3031 def __dealloc__(self):
3132 """destroy projection definition"""
32 if self.projpj is not NULL:
33 proj_destroy(self.projpj)
34 self.projpj = NULL
33 if self.projobj is not NULL:
34 proj_destroy(self.projobj)
35 self.projobj = NULL
3536
3637 @property
3738 def definition(self):
38 return self.projpj_info.definition
39 return self.projobj_info.definition
3940
4041 @property
4142 def has_inverse(self):
4243 """Returns true if this projection has an inverse"""
43 return self.projpj_info.has_inverse == 1
44 return self.projobj_info.has_inverse == 1
4445
4546 def __reduce__(self):
4647 """special method that allows pyproj.Proj instance to be pickled"""
6263 cdef double *latsdata
6364 cdef void *londata
6465 cdef void *latdata
65 cdef int err
66 cdef int errno
6667 # if buffer api is supported, get pointer to data buffers.
6768 if PyObject_AsWriteBuffer(lons, &londata, &buflenx) <> 0:
68 raise ProjError
69 raise ProjError("object does not provide the python buffer writeable interface")
6970 if PyObject_AsWriteBuffer(lats, &latdata, &bufleny) <> 0:
70 raise ProjError
71 raise ProjError("object does not provide the python buffer writeable interface")
7172 # process data in buffer
7273 if buflenx != bufleny:
7374 raise ProjError("Buffer lengths not the same")
7475 ndim = buflenx//_DOUBLESIZE
7576 lonsdata = <double *>londata
7677 latsdata = <double *>latdata
78 proj_errno_reset(self.projobj)
7779 for iii in range(ndim):
7880 # if inputs are nan's, return big number.
7981 if lonsdata[iii] != lonsdata[iii] or latsdata[iii] != latsdata[iii]:
8183 if errcheck:
8284 raise ProjError("projection_undefined")
8385 continue
84 if proj_angular_input(self.projpj, PJ_FWD):
86 if proj_angular_input(self.projobj, PJ_FWD):
8587 projlonlatin.uv.u = _DG2RAD * lonsdata[iii]
8688 projlonlatin.uv.v = _DG2RAD * latsdata[iii]
8789 else:
8890 projlonlatin.uv.u = lonsdata[iii]
8991 projlonlatin.uv.v = latsdata[iii]
90 projxyout = proj_trans(self.projpj, PJ_FWD, projlonlatin)
91 if errcheck:
92 err = proj_errno(self.projpj)
93 if err != 0:
94 raise ProjError(pystrdecode(proj_errno_string(err)))
92 projxyout = proj_trans(self.projobj, PJ_FWD, projlonlatin)
93 errno = proj_errno(self.projobj)
94 if errcheck and errno:
95 raise ProjError("proj error: {}".format(
96 pystrdecode(proj_errno_string(errno))))
97 elif errcheck and ProjError.internal_proj_error is not None:
98 raise ProjError("proj error")
9599 # since HUGE_VAL can be 'inf',
96100 # change it to a real (but very large) number.
97101 # also check for NaNs.
103107 raise ProjError("projection_undefined")
104108 lonsdata[iii] = 1.e30
105109 latsdata[iii] = 1.e30
106 elif proj_angular_output(self.projpj, PJ_FWD):
110 elif proj_angular_output(self.projobj, PJ_FWD):
107111 lonsdata[iii] = _RAD2DG * projxyout.xy.x
108112 latsdata[iii] = _RAD2DG * projxyout.xy.y
109113 else:
110114 lonsdata[iii] = projxyout.xy.x
111115 latsdata[iii] = projxyout.xy.y
116 ProjError.clear()
112117
113118
114119 @cython.boundscheck(False)
130135 cdef void *ydata
131136 cdef double *xdatab
132137 cdef double *ydatab
133 cdef int err
138 cdef int errno
134139
135140 # if buffer api is supported, get pointer to data buffers.
136141 if PyObject_AsWriteBuffer(x, &xdata, &buflenx) <> 0:
137 raise ProjError
142 raise ProjError("object does not provide the python buffer writeable interface")
138143 if PyObject_AsWriteBuffer(y, &ydata, &bufleny) <> 0:
139 raise ProjError
144 raise ProjError("object does not provide the python buffer writeable interface")
140145 # process data in buffer
141146 # (for numpy/regular python arrays).
142147 if buflenx != bufleny:
144149 ndim = buflenx//_DOUBLESIZE
145150 xdatab = <double *>xdata
146151 ydatab = <double *>ydata
152 # reset errors potentially left over
153 proj_errno_reset(self.projobj)
154
147155 for iii in range(ndim):
148156 # if inputs are nan's, return big number.
149157 if xdatab[iii] != xdatab[iii] or ydatab[iii] != ydatab[iii]:
151159 if errcheck:
152160 raise ProjError("projection_undefined")
153161 continue
154 if proj_angular_input(self.projpj, PJ_INV):
162 if proj_angular_input(self.projobj, PJ_INV):
155163 projxyin.uv.u = _DG2RAD * xdatab[iii]
156164 projxyin.uv.v = _DG2RAD * ydatab[iii]
157165 else:
158166 projxyin.uv.u = xdatab[iii]
159167 projxyin.uv.v = ydatab[iii]
160 projlonlatout = proj_trans(self.projpj, PJ_INV, projxyin)
161 if errcheck:
162 err = proj_errno(self.projpj)
163 if err != 0:
164 raise ProjError(pystrdecode(proj_errno_string(err)))
168 projlonlatout = proj_trans(self.projobj, PJ_INV, projxyin)
169 errno = proj_errno(self.projobj)
170 if errcheck and errno:
171 raise ProjError("proj error: {}".format(
172 pystrdecode(proj_errno_string(errno))))
173 elif errcheck and ProjError.internal_proj_error is not None:
174 raise ProjError("proj error")
165175 # since HUGE_VAL can be 'inf',
166176 # change it to a real (but very large) number.
167177 # also check for NaNs.
173183 raise ProjError("projection_undefined")
174184 xdatab[iii] = 1.e30
175185 ydatab[iii] = 1.e30
176 elif proj_angular_output(self.projpj, PJ_INV):
186 elif proj_angular_output(self.projobj, PJ_INV):
177187 xdatab[iii] = _RAD2DG * projlonlatout.uv.u
178188 ydatab[iii] = _RAD2DG * projlonlatout.uv.v
179189 else:
180190 xdatab[iii] = projlonlatout.uv.u
181191 ydatab[iii] = projlonlatout.uv.v
182192
193 ProjError.clear()
194
183195 def __repr__(self):
184196 return "Proj('{srs}', preserve_units=True)".format(srs=self.srs)
185197
186198 def _is_exact_same(self, Proj other):
187199 return proj_is_equivalent_to(
188 self.projpj, other.projpj, PJ_COMP_STRICT) == 1
200 self.projobj, other.projobj, PJ_COMP_STRICT) == 1
189201
190202 def _is_equivalent(self, Proj other):
191203 return proj_is_equivalent_to(
192 self.projpj, other.projpj, PJ_COMP_EQUIVALENT) == 1
204 self.projobj, other.projobj, PJ_COMP_EQUIVALENT) == 1
193205
194206 def __eq__(self, other):
195207 if not isinstance(other, Proj):
6666 cdef int is_instantiable = 0
6767 cdef CoordinateOperation coordinate_operation
6868 cdef double west_lon_degree, south_lat_degree, east_lon_degree, north_lat_degree
69
7069 operations = []
7170 try:
7271 operation_factory_context = proj_create_operation_factory_context(
141140 if pj_operations != NULL:
142141 proj_list_destroy(pj_operations)
143142 pj_operations = NULL
143 ProjError.clear()
144
144145 return operations
145146
146147
182183 def _initialize_from_projobj(self):
183184 self.proj_info = proj_pj_info(self.projobj)
184185 if self.proj_info.id == NULL:
185 ProjError.clear()
186186 raise ProjError("Input is not a transformation.")
187187 cdef PJ_TYPE transformer_type = proj_get_type(self.projobj)
188188 self.type_name = _TRANSFORMER_TYPE_MAP[transformer_type]
189 ProjError.clear()
189190
190191 @property
191192 def id(self):
227228 always_xy=False,
228229 area_of_interest=None
229230 ):
230 ProjError.clear()
231231 cdef PJ_AREA *pj_area_of_interest = NULL
232232 cdef double west_lon_degree, south_lat_degree, east_lon_degree, north_lat_degree
233233 if area_of_interest is not None:
298298
299299 @staticmethod
300300 def from_pipeline(const char *proj_pipeline):
301 ProjError.clear()
302301 cdef _Transformer transformer = _Transformer()
303302 # initialize projection
304303 transformer.projobj = proj_create(PROJ_CONTEXT.context, proj_pipeline)
328327 cdef Py_ssize_t buflenx, bufleny, buflenz, buflent, npts, iii
329328 cdef int err
330329 if PyObject_AsWriteBuffer(inx, &xdata, &buflenx) <> 0:
331 raise ProjError
330 raise ProjError("object does not provide the python buffer writeable interface")
332331 if PyObject_AsWriteBuffer(iny, &ydata, &bufleny) <> 0:
333 raise ProjError
334 if inz is not None:
335 if PyObject_AsWriteBuffer(inz, &zdata, &buflenz) <> 0:
336 raise ProjError
332 raise ProjError("object does not provide the python buffer writeable interface")
333 if inz is not None and PyObject_AsWriteBuffer(inz, &zdata, &buflenz) <> 0:
334 raise ProjError("object does not provide the python buffer writeable interface")
337335 else:
338336 buflenz = bufleny
339 if intime is not None:
340 if PyObject_AsWriteBuffer(intime, &tdata, &buflent) <> 0:
341 raise ProjError
337 if intime is not None and PyObject_AsWriteBuffer(intime, &tdata, &buflent) <> 0:
338 raise ProjError("object does not provide the python buffer writeable interface")
342339 else:
343340 buflent = bufleny
344341
370367 xx[iii] = xx[iii]*_RAD2DG
371368 yy[iii] = yy[iii]*_RAD2DG
372369
373 ProjError.clear()
374370 proj_errno_reset(self.projobj)
375371 proj_trans_generic(
376372 self.projobj,
400396 for iii in range(npts):
401397 xx[iii] = xx[iii]*_DG2RAD
402398 yy[iii] = yy[iii]*_DG2RAD
399 ProjError.clear()
403400
404401 @cython.boundscheck(False)
405402 @cython.wraparound(False)
420417 double *z
421418 double *tt
422419 Py_ssize_t buflen, npts, iii, jjj
423 int err
424420
425421 if stride < 2:
426422 raise ProjError("coordinates must contain at least 2 values")
466462 else:
467463 tt = NULL
468464
469 ProjError.clear()
470465 proj_errno_reset(self.projobj)
471466 proj_trans_generic (
472467 self.projobj,
499494 jjj = stride * iii
500495 coords[jjj] *= _DG2RAD
501496 coords[jjj + 1] *= _DG2RAD
497
498 ProjError.clear()
2323 # reset search paths
2424 from pyproj._datadir import PYPROJ_CONTEXT
2525
26 PYPROJ_CONTEXT.set_search_paths()
26 PYPROJ_CONTEXT.set_search_paths(reset=True)
2727
2828
2929 def append_data_dir(proj_data_dir):
395395 >>> lons = [-74, -102, -102, -131, -163, 163, 172, 140, 113,
396396 ... 88, 59, 25, -4, -14, -33, -46, -61]
397397 >>> poly_area, poly_perimeter = geod.polygon_area_perimeter(lons, lats)
398 >>> "{:.3f} {:.3f}".format(poly_area, poly_perimeter)
399 '13376856682207.406 14710425.407'
398 >>> "{:.1f} {:.1f}".format(poly_area, poly_perimeter)
399 '13376856682207.4 14710425.4'
400400
401401
402402 Parameters
00 import os
11 import shutil
22 import tempfile
3 import unittest
43 from contextlib import contextmanager
54
65 import pytest
76 from mock import patch
87
98 from pyproj import CRS
9 from pyproj._datadir import ContextManager
1010 from pyproj.datadir import DataDirError, append_data_dir, get_data_dir, set_data_dir
1111
1212
2626 """
2727 Ensure environment variable the same at the end of the test.
2828 """
29 proj_lib = os.environ.get("PROJ_LIB")
3029 try:
3130 yield
3231 finally:
33 if proj_lib is not None:
34 # add it back if it used to be there
35 os.environ["PROJ_LIB"] = proj_lib
36 else:
37 # remove it if it wasn't there previously
38 os.environ.pop("PROJ_LIB", None)
3932 # make sure the data dir is cleared
4033 set_data_dir(None)
4134
5245 shutil.rmtree(temp_dir)
5346
5447
55 @unittest.skipIf(os.name == "nt", reason="Cannot modify Windows environment variables.")
48 _INVALID_PATH = "/invalid/path/to/nowhere"
49
50
51 def setup_os_mock(os_mock, abspath_return=_INVALID_PATH, proj_dir=None):
52 os_mock.path.abspath.return_value = abspath_return
53 os_mock.path.join = os.path.join
54 os_mock.path.dirname = os.path.dirname
55 os_mock.path.exists = os.path.exists
56 os_mock.pathsep = os.pathsep
57 if proj_dir is None:
58 os_mock.environ = {}
59 else:
60 os_mock.environ = {"PROJ_LIB": proj_dir}
61
62
5663 def test_get_data_dir__missing():
5764 with proj_env(), pytest.raises(DataDirError), patch(
58 "pyproj.datadir.os.path.abspath", return_value="INVALID"
59 ), patch("pyproj.datadir.find_executable", return_value=None):
65 "pyproj.datadir.find_executable", return_value=None
66 ), patch("pyproj.datadir.os") as os_mock, patch("pyproj.datadir.sys") as sys_mock:
67 sys_mock.prefix = _INVALID_PATH
68 setup_os_mock(os_mock)
6069 unset_data_dir()
61 os.environ.pop("PROJ_LIB", None)
6270 assert get_data_dir() is None
6371
6472
73 def test_condext_manager_datadir_missing():
74 with proj_env(), pytest.raises(DataDirError), patch(
75 "pyproj._datadir.get_data_dir", side_effect=DataDirError("test")
76 ):
77 ContextManager().set_search_paths()
78
79
6580 def test_get_data_dir__from_user():
66 with proj_env(), temporary_directory() as tmpdir, temporary_directory() as tmpdir_env: # noqa: E501
81 with proj_env(), temporary_directory() as tmpdir, patch(
82 "pyproj.datadir.os"
83 ) as os_mock, patch(
84 "pyproj.datadir.sys"
85 ) as sys_mock, temporary_directory() as tmpdir_env: # noqa: E501
86 setup_os_mock(
87 os_mock,
88 abspath_return=os.path.join(tmpdir, "randomfilename.py"),
89 proj_dir=tmpdir_env,
90 )
91 sys_mock.prefix = tmpdir_env
6792 create_projdb(tmpdir)
68 os.environ["PROJ_LIB"] = tmpdir_env
6993 create_projdb(tmpdir_env)
7094 set_data_dir(tmpdir)
7195 internal_proj_dir = os.path.join(tmpdir, "proj_dir", "share", "proj")
7296 os.makedirs(internal_proj_dir)
7397 create_projdb(internal_proj_dir)
74 with patch("pyproj.datadir.os.path.abspath") as abspath_mock:
75 abspath_mock.return_value = os.path.join(tmpdir, "randomfilename.py")
76 assert get_data_dir() == tmpdir
98 assert get_data_dir() == tmpdir
7799
78100
79101 def test_get_data_dir__internal():
80 with proj_env(), temporary_directory() as tmpdir:
102 with proj_env(), temporary_directory() as tmpdir, patch(
103 "pyproj.datadir.os"
104 ) as os_mock, temporary_directory() as tmpdir_fake, patch(
105 "pyproj.datadir.sys"
106 ) as sys_mock:
107 setup_os_mock(
108 os_mock,
109 abspath_return=os.path.join(tmpdir, "randomfilename.py"),
110 proj_dir=tmpdir_fake,
111 )
112 sys_mock.prefix = tmpdir_fake
81113 unset_data_dir()
82 os.environ["PROJ_LIB"] = tmpdir
83114 create_projdb(tmpdir)
115 create_projdb(tmpdir_fake)
84116 internal_proj_dir = os.path.join(tmpdir, "proj_dir", "share", "proj")
85117 os.makedirs(internal_proj_dir)
86118 create_projdb(internal_proj_dir)
87 with patch("pyproj.datadir.os.path.abspath") as abspath_mock:
88 abspath_mock.return_value = os.path.join(tmpdir, "randomfilename.py")
89 assert get_data_dir() == internal_proj_dir
119 assert get_data_dir() == internal_proj_dir
90120
91121
92 @unittest.skipIf(os.name == "nt", reason="Cannot modify Windows environment variables.")
93122 def test_get_data_dir__from_env_var():
94123 with proj_env(), temporary_directory() as tmpdir, patch(
95 "pyproj.datadir.os.path.abspath", return_value="INVALID"
96 ):
124 "pyproj.datadir.os"
125 ) as os_mock, patch("pyproj.datadir.sys") as sys_mock:
126 setup_os_mock(os_mock, proj_dir=tmpdir)
127 sys_mock.prefix = _INVALID_PATH
97128 unset_data_dir()
98 os.environ["PROJ_LIB"] = tmpdir
99129 create_projdb(tmpdir)
100130 assert get_data_dir() == tmpdir
101131
102132
103 @unittest.skipIf(os.name == "nt", reason="Cannot modify Windows environment variables.")
104133 def test_get_data_dir__from_env_var__multiple():
105134 with proj_env(), temporary_directory() as tmpdir, patch(
106 "pyproj.datadir.os.path.abspath", return_value="INVALID"
107 ):
135 "pyproj.datadir.os"
136 ) as os_mock, patch("pyproj.datadir.sys") as sys_mock:
137 setup_os_mock(os_mock, proj_dir=os.pathsep.join([tmpdir, tmpdir, tmpdir]))
138 sys_mock.prefix = _INVALID_PATH
108139 unset_data_dir()
109 os.environ["PROJ_LIB"] = os.pathsep.join([tmpdir, tmpdir, tmpdir])
110140 create_projdb(tmpdir)
111141 assert get_data_dir() == os.pathsep.join([tmpdir, tmpdir, tmpdir])
112142
113143
114 @unittest.skipIf(os.name == "nt", reason="Cannot modify Windows environment variables.")
115144 def test_get_data_dir__from_prefix():
116145 with proj_env(), temporary_directory() as tmpdir, patch(
117 "pyproj.datadir.os.path.abspath", return_value="INVALID"
118 ), patch("pyproj.datadir.sys") as sys_mock:
146 "pyproj.datadir.os"
147 ) as os_mock, patch("pyproj.datadir.sys") as sys_mock:
148 setup_os_mock(os_mock)
119149 unset_data_dir()
120 os.environ.pop("PROJ_LIB", None)
121150 sys_mock.prefix = tmpdir
122151 proj_dir = os.path.join(tmpdir, "share", "proj")
123152 os.makedirs(proj_dir)
125154 assert get_data_dir() == proj_dir
126155
127156
128 @unittest.skipIf(os.name == "nt", reason="Cannot modify Windows environment variables.")
129157 def test_get_data_dir__from_path():
130158 with proj_env(), temporary_directory() as tmpdir, patch(
131 "pyproj.datadir.os.path.abspath", return_value="INVALID"
132 ), patch("pyproj.datadir.find_executable") as find_exe:
159 "pyproj.datadir.os"
160 ) as os_mock, patch("pyproj.datadir.sys") as sys_mock, patch(
161 "pyproj.datadir.find_executable"
162 ) as find_exe:
163 setup_os_mock(os_mock)
164 sys_mock.prefix = _INVALID_PATH
133165 unset_data_dir()
134 os.environ.pop("PROJ_LIB", None)
135166 find_exe.return_value = os.path.join(tmpdir, "bin", "proj")
136167 proj_dir = os.path.join(tmpdir, "share", "proj")
137168 os.makedirs(proj_dir)
140171
141172
142173 def test_append_data_dir__internal():
143 with proj_env(), temporary_directory() as tmpdir:
174 with proj_env(), temporary_directory() as tmpdir, patch(
175 "pyproj.datadir.os"
176 ) as os_mock:
177 setup_os_mock(os_mock, os.path.join(tmpdir, "randomfilename.py"))
144178 unset_data_dir()
145 os.environ["PROJ_LIB"] = tmpdir
146179 create_projdb(tmpdir)
147180 internal_proj_dir = os.path.join(tmpdir, "proj_dir", "share", "proj")
148181 os.makedirs(internal_proj_dir)
149182 create_projdb(internal_proj_dir)
150183 extra_datadir = str(os.path.join(tmpdir, "extra_datumgrids"))
151 with patch("pyproj.datadir.os.path.abspath") as abspath_mock:
152 abspath_mock.return_value = os.path.join(tmpdir, "randomfilename.py")
153 append_data_dir(extra_datadir)
154 assert get_data_dir() == os.pathsep.join([internal_proj_dir, extra_datadir])
184 append_data_dir(extra_datadir)
185 assert get_data_dir() == os.pathsep.join([internal_proj_dir, extra_datadir])
155186
156187
157188 def test_creating_multiple_crs_without_file_limit():
22 pytest can conveniently run all the tests in a single command line.
33 """
44 import os
5 import platform
56
67 import pyproj
78
1415 try:
1516 import shapely # noqa
1617 except ImportError:
17 if os.name == "nt":
18 if os.name == "nt" or platform.uname()[4] != "x86_64":
1819 expected_failure_count = 6
1920
2021 # if the below line fails, doctests have failed
00 import math
11 import os
22 import pickle
3 import platform
34 import shutil
45 import tempfile
56 from contextlib import contextmanager
2526 SHAPELY_LOADED = False
2627
2728
28 skip_shapely_windows = pytest.mark.skipif(
29 not SHAPELY_LOADED and os.name == "nt", reason="Missing shapely wheels for Windows."
29 skip_shapely = pytest.mark.skipif(
30 not SHAPELY_LOADED and (os.name == "nt" or platform.uname()[4] != "x86_64"),
31 reason="Missing shapely wheels for Windows.",
3032 )
3133
3234
170172 assert perimeter == 0
171173
172174
173 @skip_shapely_windows
175 @skip_shapely
174176 def test_geometry_length__point():
175177 geod = Geod(ellps="WGS84")
176178 assert geod.geometry_length(Point(1, 2)) == 0
177179
178180
179 @skip_shapely_windows
181 @skip_shapely
180182 def test_geometry_length__linestring():
181183 geod = Geod(ellps="WGS84")
182184 assert_almost_equal(
183185 geod.geometry_length(LineString([Point(1, 2), Point(3, 4)])),
184186 313588.39721259556,
185 decimal=3,
186 )
187
188
189 @skip_shapely_windows
187 decimal=2,
188 )
189
190
191 @skip_shapely
190192 def test_geometry_length__linestring__radians():
191193 geod = Geod(ellps="WGS84")
192194 assert_almost_equal(
200202 radians=True,
201203 ),
202204 313588.39721259556,
203 decimal=3,
204 )
205
206
207 @skip_shapely_windows
205 decimal=2,
206 )
207
208
209 @skip_shapely
208210 def test_geometry_length__linearring():
209211 geod = Geod(ellps="WGS84")
210212 assert_almost_equal(
212214 LinearRing(LineString([Point(1, 2), Point(3, 4), Point(5, 2)]))
213215 ),
214216 1072185.2103813463,
215 decimal=3,
216 )
217
218
219 @skip_shapely_windows
217 decimal=2,
218 )
219
220
221 @skip_shapely
220222 def test_geometry_length__polygon():
221223 geod = Geod(ellps="WGS84")
222224 assert_almost_equal(
224226 Polygon(LineString([Point(1, 2), Point(3, 4), Point(5, 2)]))
225227 ),
226228 1072185.2103813463,
227 decimal=3,
228 )
229
230
231 @skip_shapely_windows
229 decimal=2,
230 )
231
232
233 @skip_shapely
232234 def test_geometry_length__polygon__radians():
233235 geod = Geod(ellps="WGS84")
234236 assert_almost_equal(
245247 radians=True,
246248 ),
247249 1072185.2103813463,
248 decimal=3,
249 )
250
251
252 @skip_shapely_windows
250 decimal=2,
251 )
252
253
254 @skip_shapely
253255 def test_geometry_length__multipolygon():
254256 geod = Geod(ellps="WGS84")
255257 polygon = Polygon(LineString([Point(1, 2), Point(3, 4), Point(5, 2)]))
256258 assert_almost_equal(
257259 geod.geometry_length(MultiPolygon([polygon, polygon])),
258260 2 * 1072185.2103813463,
259 decimal=3,
260 )
261
262
263 @skip_shapely_windows
261 decimal=2,
262 )
263
264
265 @skip_shapely
264266 def test_geometry_length__multipolygon__radians():
265267 geod = Geod(ellps="WGS84")
266268 polygon = Polygon(
275277 assert_almost_equal(
276278 geod.geometry_length(MultiPolygon([polygon, polygon]), radians=True),
277279 2 * 1072185.2103813463,
278 decimal=3,
279 )
280
281
282 @skip_shapely_windows
280 decimal=2,
281 )
282
283
284 @skip_shapely
283285 def test_geometry_length__multilinestring():
284286 geod = Geod(ellps="WGS84")
285287 line_string = LineString([Point(1, 2), Point(3, 4), Point(5, 2)])
286288 assert_almost_equal(
287289 geod.geometry_length(MultiLineString([line_string, line_string])),
288290 1254353.5888503822,
289 decimal=3,
290 )
291
292
293 @skip_shapely_windows
291 decimal=2,
292 )
293
294
295 @skip_shapely
294296 def test_geometry_length__multipoint():
295297 geod = Geod(ellps="WGS84")
296298 assert (
298300 )
299301
300302
301 @skip_shapely_windows
303 @skip_shapely
302304 def test_geometry_area_perimeter__point():
303305 geod = Geod(ellps="WGS84")
304306 assert geod.geometry_area_perimeter(Point(1, 2)) == (0, 0)
305307
306308
307 @skip_shapely_windows
309 @skip_shapely
308310 def test_geometry_area_perimeter__linestring():
309311 geod = Geod(ellps="WGS84")
310312 assert_almost_equal(
311313 geod.geometry_area_perimeter(LineString([Point(1, 2), Point(3, 4)])),
312314 (0.0, 627176.7944251911),
313 decimal=3,
314 )
315
316
317 @skip_shapely_windows
315 decimal=2,
316 )
317
318
319 @skip_shapely
318320 def test_geometry_area_perimeter__linestring__radians():
319321 geod = Geod(ellps="WGS84")
320322 assert_almost_equal(
328330 radians=True,
329331 ),
330332 (0.0, 627176.7944251911),
331 decimal=3,
332 )
333
334
335 @skip_shapely_windows
333 decimal=2,
334 )
335
336
337 @skip_shapely
336338 def test_geometry_area_perimeter__linearring():
337339 geod = Geod(ellps="WGS84")
338340 assert_almost_equal(
340342 LinearRing(LineString([Point(1, 2), Point(3, 4), Point(5, 2)]))
341343 ),
342344 (-49187690467.58623, 1072185.2103813463),
343 decimal=3,
344 )
345
346
347 @skip_shapely_windows
345 decimal=2,
346 )
347
348
349 @skip_shapely
348350 def test_geometry_area_perimeter__polygon():
349351 geod = Geod(ellps="WGS84")
350352 assert_almost_equal(
352354 Polygon(LineString([Point(1, 2), Point(3, 4), Point(5, 2)]))
353355 ),
354356 (-49187690467.58623, 1072185.2103813463),
355 decimal=3,
356 )
357
358
359 @skip_shapely_windows
357 decimal=2,
358 )
359
360
361 @skip_shapely
360362 def test_geometry_area_perimeter__polygon__radians():
361363 geod = Geod(ellps="WGS84")
362364 assert_almost_equal(
373375 radians=True,
374376 ),
375377 (-49187690467.58623, 1072185.2103813463),
376 decimal=3,
377 )
378
379
380 @skip_shapely_windows
378 decimal=2,
379 )
380
381
382 @skip_shapely
381383 def test_geometry_area_perimeter__polygon__holes():
382384 geod = Geod(ellps="WGS84")
383385 assert_almost_equal(
388390 )
389391 ),
390392 (-944373881400.3394, 3979008.0359657984),
391 )
392
393
394 @skip_shapely_windows
393 decimal=2,
394 )
395
396
397 @skip_shapely
395398 def test_geometry_area_perimeter__multipolygon():
396399 geod = Geod(ellps="WGS84")
397400 polygon = Polygon(LineString([Point(1, 2), Point(3, 4), Point(5, 2)]))
398401 assert_almost_equal(
399402 geod.geometry_area_perimeter(MultiPolygon([polygon, polygon])),
400403 (-98375380935.17245, 2144370.4207626926),
401 decimal=3,
402 )
403
404
405 @skip_shapely_windows
404 decimal=2,
405 )
406
407
408 @skip_shapely
406409 def test_geometry_area_perimeter__multipolygon__radians():
407410 geod = Geod(ellps="WGS84")
408411 polygon = Polygon(
417420 assert_almost_equal(
418421 geod.geometry_area_perimeter(MultiPolygon([polygon, polygon]), radians=True),
419422 (-98375380935.17245, 2144370.4207626926),
420 decimal=3,
421 )
422
423
424 @skip_shapely_windows
423 decimal=2,
424 )
425
426
427 @skip_shapely
425428 def test_geometry_area_perimeter__multilinestring():
426429 geod = Geod(ellps="WGS84")
427430 line_string = LineString([Point(1, 2), Point(3, 4), Point(5, 2)])
428431 assert_almost_equal(
429432 geod.geometry_area_perimeter(MultiLineString([line_string, line_string])),
430433 (-98375380935.17245, 2144370.4207626926),
431 decimal=3,
432 )
433
434
435 @skip_shapely_windows
434 decimal=2,
435 )
436
437
438 @skip_shapely
436439 def test_geometry_area_perimeter__multipoint():
437440 geod = Geod(ellps="WGS84")
438441 assert geod.geometry_area_perimeter(
402402 assert not Proj("epsg:4326").is_exact_same(None)
403403
404404
405 def test_reset_errno():
406 proj = Proj(
407 {"proj": "laea", "lat_0": -90, "lon_0": 0, "a": 6371228.0, "units": "m"}
408 )
409 assert not proj.crs.is_geographic
410 assert proj(0, 0, inverse=True, errcheck=True) == (0.0, -90.0)
411
412
405413 if __name__ == "__main__":
406414 unittest.main()
0 from pkg_resources import parse_version
1
02 import numpy as np
13 import pytest
24 from numpy.testing import assert_almost_equal
9294 def test_equivalent_proj__disabled():
9395 transformer = Transformer.from_proj(3857, pyproj.Proj(3857).crs.to_proj4())
9496 assert not transformer._transformer.skip_equivalent
95 assert not transformer._transformer.projections_equivalent
97 assert transformer._transformer.projections_equivalent == (
98 parse_version(pyproj.proj_version_str) >= parse_version("6.2.0")
99 )
96100 assert not transformer._transformer.projections_exact_same
97101
98102