From 518a574423381198cbd698a3383f95000ac5354f Mon Sep 17 00:00:00 2001 From: snowman2 Date: Sat, 19 Sep 2020 20:00:28 -0500 Subject: [PATCH] REF: Remove network kwarg from Proj and Transformer --- docs/history.rst | 18 +++++----- docs/transformation_grids.rst | 8 ++--- pyproj/_crs.pyx | 3 +- pyproj/_datadir.pxd | 2 +- pyproj/_datadir.pyx | 21 ++---------- pyproj/_transformer.pyi | 64 +++++++++++++++++++++++++---------- pyproj/_transformer.pyx | 12 +++---- pyproj/proj.py | 12 +------ pyproj/transformer.py | 38 ++------------------- test/test_proj.py | 13 +++---- test/test_transformer.py | 35 ++++++++----------- 11 files changed, 89 insertions(+), 137 deletions(-) diff --git a/docs/history.rst b/docs/history.rst index ad7fbfafa..85e59d03a 100644 --- a/docs/history.rst +++ b/docs/history.rst @@ -6,27 +6,27 @@ Change Log * Minimum supported Python version 3.6 (issue #499) * Minimum PROJ version 7.2 (issues #599 & #689) * WHL: Removed datumgrids from wheels because not needed with RFC 4 (pull #628) -* Refactor Proj to inherit from Transformer (issue #624) +* ENH: Added :ref:`network` (#675, #691, #695) +* ENH: Added ability to use global context (issue #661) +* ENH: Added transformation grid sync API/CLI (issue #572) * ENH: Support obects with '__array__' method (pandas.Series, xarray.DataArray, dask.array.Array) (issue #573) * ENH: Added :func:`pyproj.datadir.get_user_data_dir` (pull #636) -* ENH: Added network methods to Transformer (issue #629) -* ENH: Use 'proj_get_units_from_database' in :func:`pyproj.get_units_map` & cleanup :func:`pyproj.get_codes` (issue #619) +* ENH: Added :attr:`pyproj.transformer.Transformer.is_network_enabled` (issue #629) +* ENH: Added :meth:`pyproj.transformer.TransformerGroup.download_grids` (pull #643) +* ENH: Use 'proj_get_units_from_database' in :func:`pyproj.database.get_units_map` & cleanup :func:`pyproj.database.get_codes` (issue #619) * ENH: Added support for radians for Proj & Transformer.from_pipeline & use less gil (issue #612) * ENH: Datum.from_name default to check all datum types (issue #606) * ENH: Use from_user_input in __eq__ when comparing CRS sub-classes (i.e. PrimeMeridian, Datum, Ellipsoid, etc.) (issue #606) -* ENH: Added :meth:`pyproj.transformer.TransformerGroup.download_grids` (pull #643) -* ENH: Added transformation grid sync API/CLI (issue #572) * ENH: Add support for coordinate systems with CRS using CF conventions (issue #536) * ENH: Use `proj_is_equivalent_to_with_ctx` in the place of `proj_is_equivalent_to` internally (issue #666) * BUG: Add support for identifying engineering/parametric/temporal datums (issue #670) -* 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 :ref:`network` (#675, #691, #695) * ENH: Added support for debugging internal PROJ (pull #696) * ENH: Added pathlib support for data directory methods (pull #702) -* ENH: Added `pyproj.database.query_crs_info` (pull #703) +* ENH: Added :func:`pyproj.database.query_crs_info` (pull #703) +* REF: Refactor Proj to inherit from Transformer (issue #624) * REF: Added `pyproj.database`, `pyproj.aoi`, and `pyproj.list` modules (pull #703) +* BUG: Fix handling of polygon holes when calculating area in Geod (pull #686) 2.6.1 ~~~~~ diff --git a/docs/transformation_grids.rst b/docs/transformation_grids.rst index 3220162ee..1ebfe1a0b 100644 --- a/docs/transformation_grids.rst +++ b/docs/transformation_grids.rst @@ -56,10 +56,7 @@ Available methods for download include: - `pyproj sync `__ command line program (pyproj 3+; useful if you use pyproj wheels). -- Enabling `PROJ network `__ capabilities. - - .. note:: You can use the `network` kwarg when initializing - :class:`pyproj.Proj` or :class:`pyproj.Transformer ` +- Enabling `PROJ network `__ capabilities. See also :ref:`network`. - Download stable from https://download.osgeo.org/proj or latest from https://github.com/OSGeo/PROJ-data @@ -91,7 +88,8 @@ What grids to download? - Have a machine that can hold and extra 500 MB - 1 GB of data? Then downloading all grids shouldn't be an issue. -- Have a machine with limited space, a great network connection, and PROJ 7+? Look into `PROJ network `__ capabilities. +- Have a machine with limited space, a great network connection, and PROJ 7+? + Look into `PROJ network `__ capabilities. See also :ref:`network`. - Have a machine with limited space and want to pre-download files? diff --git a/pyproj/_crs.pyx b/pyproj/_crs.pyx index 0f9422439..0c3c129c3 100644 --- a/pyproj/_crs.pyx +++ b/pyproj/_crs.pyx @@ -161,11 +161,10 @@ cdef _get_concatenated_operations(PJ_CONTEXT* context, PJ* concatenated_operatio ) cdef PJ* operation = NULL cdef PJ_CONTEXT* sub_context = NULL - cdef int network_enabled = proj_context_is_network_enabled(context) cdef int iii = 0 operations = [] for iii in range(step_count): - sub_context = pyproj_context_create(network=network_enabled) + sub_context = pyproj_context_create() operation = proj_concatoperation_get_step( sub_context, concatenated_operation, diff --git a/pyproj/_datadir.pxd b/pyproj/_datadir.pxd index 1a7332429..1a9e0b0ae 100644 --- a/pyproj/_datadir.pxd +++ b/pyproj/_datadir.pxd @@ -1,4 +1,4 @@ include "proj.pxi" -cdef PJ_CONTEXT* pyproj_context_create(network=*) except * +cdef PJ_CONTEXT* pyproj_context_create() except * diff --git a/pyproj/_datadir.pyx b/pyproj/_datadir.pyx index 1d820e534..2927350c7 100644 --- a/pyproj/_datadir.pyx +++ b/pyproj/_datadir.pyx @@ -120,19 +120,8 @@ cdef void set_context_data_dir(PJ_CONTEXT* context) except *: free(c_data_dir) -cdef void pyproj_context_set_enable_network( - PJ_CONTEXT* context, - network=None, -) except *: - if network is not None: - enabled = proj_context_set_enable_network(context, bool(network)) - if network and not enabled: - warnings.warn("PROJ network cannot be enabled.") - - cdef void pyproj_context_initialize( PJ_CONTEXT* context, - network=None, bint autoclose_database=True, ) except *: """ @@ -142,13 +131,10 @@ cdef void pyproj_context_initialize( proj_context_use_proj4_init_rules(context, 1) if autoclose_database: proj_context_set_autoclose_database(context, 1) - pyproj_context_set_enable_network(context, network=network) set_context_data_dir(context) -cdef PJ_CONTEXT* pyproj_context_create( - network=None, -) except *: +cdef PJ_CONTEXT* pyproj_context_create() except *: """ Create and initialize the context(s) for pyproj. This also manages whether the global context is used. @@ -156,16 +142,13 @@ cdef PJ_CONTEXT* pyproj_context_create( global _USE_GLOBAL_CONTEXT if _USE_GLOBAL_CONTEXT: return NULL - cdef PJ_CONTEXT* context = proj_context_create() - pyproj_context_set_enable_network(context, network=network) - return context + return proj_context_create() def _pyproj_global_context_initialize(): global _USE_GLOBAL_CONTEXT pyproj_context_initialize( NULL, - network=None, autoclose_database=not _USE_GLOBAL_CONTEXT ) diff --git a/pyproj/_transformer.pyi b/pyproj/_transformer.pyi index d0e0bbd10..9b57fae7e 100644 --- a/pyproj/_transformer.pyi +++ b/pyproj/_transformer.pyi @@ -6,12 +6,14 @@ from pyproj.enums import TransformDirection proj_version_str: str + class AreaOfInterest(NamedTuple): west_lon_degree: float south_lat_degree: float east_lon_degree: float north_lat_degree: float + class Factors(NamedTuple): meridional_scale: float parallel_scale: float @@ -26,10 +28,12 @@ class Factors(NamedTuple): dy_dlam: float dy_dphi: float + class _TransformerGroup: _transformers: Any _unavailable_operations: List[CoordinateOperation] _best_available: bool + def __init__( self, crs_from: _CRS, @@ -37,8 +41,9 @@ class _TransformerGroup: skip_equivalent: bool = False, always_xy: bool = False, area_of_interest: Optional[AreaOfInterest] = None, - network: Optional[bool] = None, - ) -> None: ... + ) -> None: + ... + class _Transformer(Base): input_geographic: bool @@ -48,22 +53,39 @@ class _Transformer(Base): projections_equivalent: bool projections_exact_same: bool type_name: str + @property - def id(self) -> str: ... + def id(self) -> str: + ... + @property - def description(self) -> str: ... + def description(self) -> str: + ... + @property - def definition(self) -> str: ... + def definition(self) -> str: + ... + @property - def has_inverse(self) -> bool: ... + def has_inverse(self) -> bool: + ... + @property - def accuracy(self) -> float: ... + def accuracy(self) -> float: + ... + @property - def area_of_use(self) -> AreaOfUse: ... + def area_of_use(self) -> AreaOfUse: + ... + @property - def operations(self) -> Union[Tuple[CoordinateOperation], None]: ... + def operations(self) -> Union[Tuple[CoordinateOperation], None]: + ... + @property - def is_network_enabled(self) -> bool: ... + def is_network_enabled(self) -> bool: + ... + @staticmethod def from_crs( crs_from: _CRS, @@ -71,12 +93,13 @@ class _Transformer(Base): skip_equivalent: bool = False, always_xy: bool = False, area_of_interest: Optional[AreaOfInterest] = None, - network: Optional[bool] = None, - ) -> "_Transformer": ... + ) -> "_Transformer": + ... + @staticmethod - def from_pipeline( - proj_pipeline: str, network: Optional[bool] = None - ) -> "_Transformer": ... + def from_pipeline(proj_pipeline: str) -> "_Transformer": + ... + def _transform( self, inx: Any, @@ -86,7 +109,9 @@ class _Transformer(Base): direction: Union[TransformDirection, str], radians: bool, errcheck: bool, - ) -> None: ... + ) -> None: + ... + def _transform_sequence( self, stride: int, @@ -96,7 +121,10 @@ class _Transformer(Base): time_3rd: bool, radians: bool, errcheck: bool, - ) -> None: ... + ) -> None: + ... + def _get_factors( self, longitude: Any, latitude: Any, radians: bool, errcheck: bool - ) -> Factors: ... + ) -> Factors: + ... diff --git a/pyproj/_transformer.pyx b/pyproj/_transformer.pyx index 162625fe5..7418d9ed1 100644 --- a/pyproj/_transformer.pyx +++ b/pyproj/_transformer.pyx @@ -113,7 +113,6 @@ cdef class _TransformerGroup: skip_equivalent=False, always_xy=False, area_of_interest=None, - network=None, ): """ From PROJ docs: @@ -124,7 +123,7 @@ cdef class _TransformerGroup: area of use of the CRS), and by increasing accuracy. Operations with unknown accuracy are sorted last, whatever their area. """ - self.context = pyproj_context_create(network=network) + self.context = pyproj_context_create() cdef PJ_OPERATION_FACTORY_CONTEXT* operation_factory_context = NULL cdef PJ_OBJ_LIST * pj_operations = NULL cdef PJ* pj_transform = NULL @@ -174,7 +173,7 @@ cdef class _TransformerGroup: ) num_operations = proj_list_get_count(pj_operations) for iii in range(num_operations): - context = pyproj_context_create(network=network) + context = pyproj_context_create() pj_transform = proj_list_get( context, pj_operations, @@ -306,7 +305,6 @@ cdef class _Transformer(Base): skip_equivalent=False, always_xy=False, area_of_interest=None, - network=None, ): """ Create a transformer from CRS objects @@ -336,7 +334,7 @@ cdef class _Transformer(Base): east_lon_degree, north_lat_degree, ) - transformer.context = pyproj_context_create(network=network) + transformer.context = pyproj_context_create() transformer.projobj = proj_create_crs_to_crs( transformer.context, cstrencode(crs_from.srs), @@ -386,12 +384,12 @@ cdef class _Transformer(Base): return transformer @staticmethod - def from_pipeline(const char *proj_pipeline, network=None): + def from_pipeline(const char *proj_pipeline): """ Create Transformer from a PROJ pipeline string. """ cdef _Transformer transformer = _Transformer() - transformer.context = pyproj_context_create(network=network) + transformer.context = pyproj_context_create() # initialize projection transformer.projobj = proj_create( transformer.context, diff --git a/pyproj/proj.py b/pyproj/proj.py index f5c4c2a29..7142a7b1a 100644 --- a/pyproj/proj.py +++ b/pyproj/proj.py @@ -48,7 +48,6 @@ def __init__( self, projparams: Any = None, preserve_units: bool = True, - network=None, **kwargs, ) -> None: """ @@ -59,19 +58,12 @@ def __init__( https://proj.org/operations/projections/index.html for examples of key/value pairs defining different map projections. - .. versionadded:: 3.0.0 network - Parameters ---------- projparams: int, str, dict, pyproj.CRS A PROJ or WKT string, PROJ dict, EPSG integer, or a pyproj.CRS instance. preserve_units: bool If false, will ensure +units=m. - network: bool, optional - Default is None, which uses the system defaults for networking. - If True, it will force the use of network for grids regardless of - any other network setting. If False, it will force disable use of - network for grids regardless of any other network setting. **kwargs: PROJ projection parameters. @@ -142,9 +134,7 @@ def __init__( projstring = self.crs.to_proj4() or self.crs.srs self.srs = re.sub(r"\s\+?type=crs", "", projstring).strip() - super().__init__( - _Transformer.from_pipeline(cstrencode(self.srs), network=network) - ) + super().__init__(_Transformer.from_pipeline(cstrencode(self.srs))) def __call__( self, diff --git a/pyproj/transformer.py b/pyproj/transformer.py index ff5c2270c..280affaf7 100644 --- a/pyproj/transformer.py +++ b/pyproj/transformer.py @@ -54,7 +54,6 @@ def __init__( skip_equivalent: bool = False, always_xy: bool = False, area_of_interest: Optional[AreaOfInterest] = None, - network: Optional[bool] = None, ) -> None: """Get all possible transformations from a :obj:`pyproj.crs.CRS` or input used to create one. @@ -77,11 +76,6 @@ def __init__( area_of_interest: :class:`pyproj.transformer.AreaOfInterest`, optional The area of interest to help order the transformations based on the best operation for the area. - network: bool, optional - Default is None, which uses the system defaults for networking. - If True, it will force the use of network for grids regardless of - any other network setting. If False, it will force disable use of - network for grids regardless of any other network setting. """ super().__init__( @@ -90,7 +84,6 @@ def __init__( skip_equivalent=skip_equivalent, always_xy=always_xy, area_of_interest=area_of_interest, - network=network, ) for iii, transformer in enumerate(self._transformers): self._transformers[iii] = Transformer(transformer) @@ -291,14 +284,12 @@ def from_proj( skip_equivalent: bool = False, always_xy: bool = False, area_of_interest: Optional[AreaOfInterest] = None, - network: Optional[bool] = None, ) -> "Transformer": """Make a Transformer from a :obj:`pyproj.Proj` or input used to create one. .. versionadded:: 2.1.2 skip_equivalent .. versionadded:: 2.2.0 always_xy .. versionadded:: 2.3.0 area_of_interest - .. versionadded:: 3.0.0 network Parameters ---------- @@ -316,11 +307,6 @@ def from_proj( Default is false. area_of_interest: :class:`pyproj.transformer.AreaOfInterest`, optional The area of interest to help select the transformation. - network: bool, optional - Default is None, which uses the system defaults for networking. - If True, it will force the use of network for grids regardless of - any other network setting. If False, it will force disable use of - network for grids regardless of any other network setting. Returns ------- @@ -340,7 +326,6 @@ def from_proj( skip_equivalent=skip_equivalent, always_xy=always_xy, area_of_interest=area_of_interest, - network=network, ) @staticmethod @@ -350,14 +335,12 @@ def from_crs( skip_equivalent: bool = False, always_xy: bool = False, area_of_interest: Optional[AreaOfInterest] = None, - network: Optional[bool] = None, ) -> "Transformer": """Make a Transformer from a :obj:`pyproj.crs.CRS` or input used to create one. .. versionadded:: 2.1.2 skip_equivalent .. versionadded:: 2.2.0 always_xy .. versionadded:: 2.3.0 area_of_interest - .. versionadded:: 3.0.0 network Parameters ---------- @@ -375,11 +358,6 @@ def from_crs( Default is false. area_of_interest: :class:`pyproj.transformer.AreaOfInterest`, optional The area of interest to help select the transformation. - network: bool, optional - Default is None, which uses the system defaults for networking. - If True, it will force the use of network for grids regardless of - any other network setting. If False, it will force disable use of - network for grids regardless of any other network setting. Returns ------- @@ -393,38 +371,26 @@ def from_crs( skip_equivalent=skip_equivalent, always_xy=always_xy, area_of_interest=area_of_interest, - network=network, ) ) @staticmethod - def from_pipeline( - proj_pipeline: str, network: Optional[bool] = None - ) -> "Transformer": + def from_pipeline(proj_pipeline: str) -> "Transformer": """Make a Transformer from a PROJ pipeline string. https://proj.org/operations/pipeline.html - .. versionadded:: 3.0.0 network - Parameters ---------- proj_pipeline: str Projection pipeline string. - network: bool, optional - Default is None, which uses the system defaults for networking. - If True, it will force the use of network for grids regardless of - any other network setting. If False, it will force disable use of - network for grids regardless of any other network setting. Returns ------- Transformer """ - return Transformer( - _Transformer.from_pipeline(cstrencode(proj_pipeline), network=network) - ) + return Transformer(_Transformer.from_pipeline(cstrencode(proj_pipeline))) def transform( self, diff --git a/test/test_proj.py b/test/test_proj.py index c3c44356a..da986d556 100644 --- a/test/test_proj.py +++ b/test/test_proj.py @@ -534,25 +534,22 @@ def test_numpy_bool_kwarg_true(): @patch.dict("os.environ", {"PROJ_NETWORK": "ON"}, clear=True) def test_network__disable(): with proj_network_env(): - if pyproj._datadir._USE_GLOBAL_CONTEXT: - pyproj.network.set_network_enabled(active=False) - transformer = Proj(3857, network=False) + pyproj.network.set_network_enabled(active=False) + transformer = Proj(3857) assert transformer.is_network_enabled is False @patch.dict("os.environ", {"PROJ_NETWORK": "OFF"}, clear=True) def test_network__enable(): with proj_network_env(): - if pyproj._datadir._USE_GLOBAL_CONTEXT: - pyproj.network.set_network_enabled(active=True) - transformer = Proj(3857, network=True) + pyproj.network.set_network_enabled(active=True) + transformer = Proj(3857) assert transformer.is_network_enabled is True def test_network__default(): with proj_network_env(): - if pyproj._datadir._USE_GLOBAL_CONTEXT: - pyproj.network.set_network_enabled() + pyproj.network.set_network_enabled() transformer = Proj(3857) assert transformer.is_network_enabled == ( os.environ.get("PROJ_NETWORK") == "ON" diff --git a/test/test_transformer.py b/test/test_transformer.py index de737222f..73874b55e 100644 --- a/test/test_transformer.py +++ b/test/test_transformer.py @@ -792,9 +792,8 @@ def test_pipeline_itransform(pipeline_str): @patch.dict("os.environ", {"PROJ_NETWORK": "ON"}, clear=True) def test_network__disable(transformer): with proj_network_env(): - if pyproj._datadir._USE_GLOBAL_CONTEXT: - pyproj.network.set_network_enabled(active=False) - trans = transformer(network=False) + pyproj.network.set_network_enabled(active=False) + trans = transformer() assert trans.is_network_enabled is False @@ -811,9 +810,8 @@ def test_network__disable(transformer): @patch.dict("os.environ", {"PROJ_NETWORK": "OFF"}, clear=True) def test_network__enable(transformer): with proj_network_env(): - if pyproj._datadir._USE_GLOBAL_CONTEXT: - pyproj.network.set_network_enabled(active=True) - trans = transformer(network=True) + pyproj.network.set_network_enabled(active=True) + trans = transformer() assert trans.is_network_enabled is True @@ -829,8 +827,7 @@ def test_network__enable(transformer): ) def test_network__default(transformer): with proj_network_env(): - if pyproj._datadir._USE_GLOBAL_CONTEXT: - pyproj.network.set_network_enabled() + pyproj.network.set_network_enabled() trans = transformer() assert trans.is_network_enabled == (os.environ.get("PROJ_NETWORK") == "ON") @@ -838,9 +835,8 @@ def test_network__default(transformer): @patch.dict("os.environ", {"PROJ_NETWORK": "OFF"}, clear=True) def test_transformer_group__network_enabled(): with proj_network_env(): - if pyproj._datadir._USE_GLOBAL_CONTEXT: - pyproj.network.set_network_enabled(active=True) - trans_group = TransformerGroup(4326, 2964, network=True) + pyproj.network.set_network_enabled(active=True) + trans_group = TransformerGroup(4326, 2964) assert len(trans_group.unavailable_operations) == 0 assert len(trans_group.transformers) == 10 assert trans_group.best_available @@ -854,9 +850,8 @@ def test_transformer_group__network_enabled(): @patch.dict("os.environ", {"PROJ_NETWORK": "ON"}, clear=True) def test_transformer_group__network_disabled(): with proj_network_env(): - if pyproj._datadir._USE_GLOBAL_CONTEXT: - pyproj.network.set_network_enabled(active=False) - trans_group = TransformerGroup(4326, 2964, network=False) + pyproj.network.set_network_enabled(active=False) + trans_group = TransformerGroup(4326, 2964) for transformer in trans_group.transformers: assert transformer.is_network_enabled is False @@ -956,9 +951,8 @@ def test_transform_honours_input_types(x, y, z): def test_transformer_group__download_grids(get_user_data_dir_mock, tmp_path, capsys): get_user_data_dir_mock.return_value = str(tmp_path) with proj_network_env(): - if pyproj._datadir._USE_GLOBAL_CONTEXT: - pyproj.network.set_network_enabled(active=False) - trans_group = TransformerGroup(4326, 2964, network=False) + pyproj.network.set_network_enabled(active=False) + trans_group = TransformerGroup(4326, 2964) trans_group.download_grids(verbose=True) captured = capsys.readouterr() get_user_data_dir_mock.assert_called_with(True) @@ -992,7 +986,7 @@ def test_transformer_group__download_grids(get_user_data_dir_mock, tmp_path, cap "pyproj.transformer._download_resource_file" ) as download_mock: append_data_dir(str(tmp_path)) - trans_group = TransformerGroup(4326, 2964, network=False) + trans_group = TransformerGroup(4326, 2964) trans_group.download_grids() get_user_data_dir_mock.assert_called_with(True) download_mock.assert_not_called() @@ -1004,9 +998,8 @@ def test_transformer_group__download_grids__directory( get_user_data_dir_mock, download_mock, tmp_path, capsys ): with proj_network_env(): - if pyproj._datadir._USE_GLOBAL_CONTEXT: - pyproj.network.set_network_enabled(active=False) - trans_group = TransformerGroup(4326, 2964, network=False) + pyproj.network.set_network_enabled(active=False) + trans_group = TransformerGroup(4326, 2964) trans_group.download_grids(directory=tmp_path) get_user_data_dir_mock.assert_not_called() captured = capsys.readouterr()