From f3156505d91ab05aca418c049d40be9f00ecbdc5 Mon Sep 17 00:00:00 2001 From: "Alan D. Snow" Date: Tue, 5 May 2020 08:35:53 -0500 Subject: [PATCH] Drop support for python 3.5 (#617) --- .pre-commit-config.yaml | 1 + .travis.yml | 1 - Makefile | 4 +- docs/advanced_examples.rst | 2 +- docs/conf.py | 12 +-- docs/examples.rst | 8 +- docs/history.rst | 4 + docs/index.rst | 2 +- pyproj/__init__.py | 2 +- pyproj/__main__.py | 2 +- pyproj/_crs.pyx | 166 +++++++++-------------------- pyproj/_geod.pyx | 13 +-- pyproj/_proj.pyx | 25 +++-- pyproj/_show_versions.py | 2 +- pyproj/_transformer.pyx | 14 +-- pyproj/crs/coordinate_operation.py | 23 ++-- pyproj/crs/crs.py | 66 +++++------- pyproj/enums.py | 6 +- pyproj/exceptions.py | 5 +- pyproj/geod.py | 78 +++++++------- pyproj/proj.py | 6 +- pyproj/transformer.py | 30 ++---- setup.py | 17 ++- test/crs/test_crs.py | 6 +- test/test_doctest_wrapper.py | 2 +- test/test_proj.py | 2 +- test/test_transformer.py | 4 +- 27 files changed, 196 insertions(+), 307 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 53e2e6c85..9aa9110d2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -9,6 +9,7 @@ repos: rev: 19.10b0 hooks: - id: black + args: [--target-version, py36] - repo: https://github.com/timothycrosley/isort rev: 4.3.21 hooks: diff --git a/.travis.yml b/.travis.yml index d011a2c9b..3bbddf2ee 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,7 +26,6 @@ matrix: os: osx env: - PYTHON=3.6.8 - - python: 3.5 - python: 3.6 - python: 3.6 env: diff --git a/Makefile b/Makefile index 5eb070574..ea8554fa3 100644 --- a/Makefile +++ b/Makefile @@ -68,14 +68,14 @@ check-type: mypy pyproj check: lint check-type ## flake8 black isort check - black --check setup.py pyproj/ test/ docs/ + black --check --target-version py36 setup.py pyproj/ test/ docs/ isort --check --recursive setup.py pyproj/ test/ docs/ isort: ## order imports isort --recursive setup.py pyproj/ test/ docs/ black: ## black format files - black setup.py pyproj/ test/ docs/ + black --target-version py36 setup.py pyproj/ test/ docs/ test: ## run tests py.test diff --git a/docs/advanced_examples.rst b/docs/advanced_examples.rst index 55d3b5e95..a03938381 100644 --- a/docs/advanced_examples.rst +++ b/docs/advanced_examples.rst @@ -93,7 +93,7 @@ transformations as well as missing transformations. >>> from pyproj.transformer import TransformerGroup >>> tg = TransformerGroup("epsg:4326", "+proj=aea +lat_0=50 +lon_0=-154 +lat_1=55 +lat_2=65 +x_0=0 +y_0=0 +datum=NAD27 +no_defs +type=crs +units=m", always_xy=True) UserWarning: Best transformation is not available due to missing Grid(short_name=ntv2_0.gsb, full_name=, package_name=proj-datumgrid-north-america, url=https://download.osgeo.org/proj/proj-datumgrid-north-america-latest.zip, direct_download=True, open_license=True, available=False) - "{!r}".format(operation.grids[0]) + f"{operation.grids[0]!r}" >>> tg - transformers: 37 diff --git a/docs/conf.py b/docs/conf.py index a7b84dfe0..e25ffe24c 100755 --- a/docs/conf.py +++ b/docs/conf.py @@ -53,9 +53,9 @@ master_doc = "index" # General information about the project. -project = u"pyproj" -copyright = u"2006-2018, Jeffrey Whitaker; 2019-2020, Open source contributors" -author = u"Jeffrey Whitaker" +project = "pyproj" +copyright = "2006-2018, Jeffrey Whitaker; 2019-2020, Open source contributors" +author = "Jeffrey Whitaker" # The version info for the project you're documenting, acts as replacement # for |version| and |release|, also used in various other places throughout @@ -131,7 +131,7 @@ # (source start file, target name, title, author, documentclass # [howto, manual, or own class]). latex_documents = [ - (master_doc, "pyproj.tex", u"pyproj Documentation", u"Delta", "manual") + (master_doc, "pyproj.tex", "pyproj Documentation", "Delta", "manual") ] @@ -139,7 +139,7 @@ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). -man_pages = [(master_doc, "pyproj", u"pyproj Documentation", [author], 1)] +man_pages = [(master_doc, "pyproj", "pyproj Documentation", [author], 1)] # -- Options for Texinfo output ---------------------------------------- @@ -151,7 +151,7 @@ ( master_doc, "pyproj", - u"pyproj Documentation", + "pyproj Documentation", author, "pyproj", "One line description of project.", diff --git a/docs/examples.rst b/docs/examples.rst index 6147dd39e..4615eac78 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -402,7 +402,7 @@ Calculate the geodesic length of a line (See: :meth:`pyproj.Geod.line_length`): ... 88, 59, 25, -4, -14, -33, -46, -61] >>> geod = Geod(ellps="WGS84") >>> total_length = geod.line_length(lons, lats) - >>> "{:.3f}".format(total_length) + >>> f"{total_length:.3f}" '14259605.611' Calculate the geodesic length of a shapely geometry (See: :meth:`pyproj.Geod.geometry_length`): @@ -414,7 +414,7 @@ Calculate the geodesic length of a shapely geometry (See: :meth:`pyproj.Geod.geo >>> line_string = LineString([Point(1, 2), Point(3, 4)])) >>> geod = Geod(ellps="WGS84") >>> total_length = geod.geometry_length(line_string) - >>> "{:.3f}".format(total_length) + >>> f"{total_length:.3f}" '313588.397' @@ -432,7 +432,7 @@ Calculate the geodesic area and perimeter of a polygon (See: :meth:`pyproj.Geod. >>> lons = [-74, -102, -102, -131, -163, 163, 172, 140, 113, ... 88, 59, 25, -4, -14, -33, -46, -61] >>> poly_area, poly_perimeter = geod.polygon_area_perimeter(lons, lats) - >>> "{:.3f} {:.3f}".format(poly_area, poly_perimeter) + >>> f"{poly_area:.3f} {poly_perimeter:.3f}" '13376856682207.406 14710425.407' @@ -450,5 +450,5 @@ Calculate the geodesic area and perimeter of a shapely polygon (See: :meth:`pypr holes=[LineString([Point(1, 2), Point(3, 4), Point(5, 2)])], ) ) - >>> "{:.3f} {:.3f}".format(poly_area, poly_perimeter) + >>> f"{poly_area:.3f} {poly_perimeter:.3f}" '-944373881400.339 3979008.036' diff --git a/docs/history.rst b/docs/history.rst index ac871a666..2f8a51bef 100644 --- a/docs/history.rst +++ b/docs/history.rst @@ -1,6 +1,10 @@ Change Log ========== +3.0.0 +----- +* Minimum supported Python version 3.6 (issue #499) + 2.6.1 ~~~~~ * WHL: Wheels contain PROJ version is 7.0.1 diff --git a/docs/index.rst b/docs/index.rst index 0c11ae537..321b08d31 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -5,7 +5,7 @@ Python interface to `PROJ `_ (cartographic projections and c .. note:: Minimum supported PROJ version is 6.2.0 -.. note:: Minimum supported Python version is 3.5 +.. note:: Minimum supported Python version is 3.6 GitHub Repository: https://github.com/pyproj4/pyproj diff --git a/pyproj/__init__.py b/pyproj/__init__.py index 5b9c93e5a..b9cb74495 100644 --- a/pyproj/__init__.py +++ b/pyproj/__init__.py @@ -4,7 +4,7 @@ Download: http://python.org/pypi/pyproj -Requirements: Python 3.5+. +Requirements: Python 3.6+. Contact: Jeffrey Whitaker diff --git a/pyproj/__main__.py b/pyproj/__main__.py index cc2f8bb4b..d4fa8fb98 100644 --- a/pyproj/__main__.py +++ b/pyproj/__main__.py @@ -20,5 +20,5 @@ if args.verbose: _show_versions.show_versions() else: - print("pyproj version: {} [PROJ version: {}]".format(__version__, __proj_version__)) + print(f"pyproj version: {__version__} [PROJ version: {__proj_version__}]") parser.print_help() diff --git a/pyproj/_crs.pyx b/pyproj/_crs.pyx index 9780bc0c3..c972cbd8c 100644 --- a/pyproj/_crs.pyx +++ b/pyproj/_crs.pyx @@ -262,23 +262,13 @@ cdef class Axis: self.unit_code = "undefined" def __str__(self): - return "{abbrev}[{direction}]: {name} ({unit_name})".format( - name=self.name, - direction=self.direction, - abbrev=self.abbrev, - unit_name=self.unit_name, - ) + return f"{self.abbrev}[{self.direction}]: {self.name} ({self.unit_name})" def __repr__(self): - return ("Axis(name={name}, abbrev={abbrev}, direction={direction}, " - "unit_auth_code={unit_auth_code}, unit_code={unit_code}, " - "unit_name={unit_name})").format( - name=self.name, - abbrev=self.abbrev, - direction=self.direction, - unit_name=self.unit_name, - unit_auth_code=self.unit_auth_code, - unit_code=self.unit_code, + return ( + f"Axis(name={self.name}, abbrev={self.abbrev}, " + f"direction={self.direction}, unit_auth_code={self.unit_auth_code}, " + f"unit_code={self.unit_code}, unit_name={self.unit_name})" ) @staticmethod @@ -339,18 +329,15 @@ cdef class AreaOfUse: self.name = "undefined" def __str__(self): - return "- name: {name}\n" \ - "- bounds: {bounds}".format( - name=self.name, bounds=self.bounds) + return ( + f"- name: {self.name}\n" + f"- bounds: {self.bounds}" + ) def __repr__(self): - return ("AreaOfUse(name={name}, west={west}, south={south}," - " east={east}, north={north})").format( - name=self.name, - west=self.west, - south=self.south, - east=self.east, - north=self.north + return ( + f"AreaOfUse(name={self.name}, west={self.west}, south={self.south}," + f" east={self.east}, north={self.north})" ) @staticmethod @@ -477,9 +464,7 @@ cdef class Base: multiline = b"MULTILINE=NO" if pretty: multiline = b"MULTILINE=YES" - indentation_width = cstrencode( - "INDENTATION_WIDTH={:.0f}".format(indentation) - ) + indentation_width = cstrencode(f"INDENTATION_WIDTH={indentation:.0f}") options[0] = multiline options[1] = indentation_width options[2] = NULL @@ -569,10 +554,7 @@ cdef class _CRSParts(Base): elif hasattr(user_input, "to_json"): prepared = cls.from_json(user_input.to_json()) else: - raise CRSError("Invalid {} input: {!r}".format( - cls.__name__, - user_input, - )) + raise CRSError(f"Invalid {cls.__name__} input: {user_input!r}") return prepared @@ -676,9 +658,8 @@ cdef class CoordinateSystem(_CRSParts): proj_destroy(coordinate_system_pj) proj_context_destroy(context) raise CRSError( - "Invalid coordinate system string: {}".format( - pystrdecode(coordinate_system_string) - ) + "Invalid coordinate system string: " + f"{pystrdecode(coordinate_system_string)}" ) CRSError.clear() return CoordinateSystem.create(context, coordinate_system_pj) @@ -804,9 +785,7 @@ cdef class Ellipsoid(_CRSParts): if ellipsoid_pj == NULL: proj_context_destroy(context) - raise CRSError( - "Invalid authority or code ({0}, {1})".format(auth_name, code) - ) + raise CRSError(f"Invalid authority or code ({auth_name}, {code})") CRSError.clear() return Ellipsoid.create(context, ellipsoid_pj) @@ -858,9 +837,7 @@ cdef class Ellipsoid(_CRSParts): proj_destroy(ellipsoid_pj) proj_context_destroy(context) raise CRSError( - "Invalid ellipsoid string: {}".format( - pystrdecode(ellipsoid_string) - ) + f"Invalid ellipsoid string: {pystrdecode(ellipsoid_string)}" ) CRSError.clear() return Ellipsoid.create(context, ellipsoid_pj) @@ -964,11 +941,7 @@ cdef class Ellipsoid(_CRSParts): ) if ellipsoid_pj == NULL: proj_context_destroy(context) - raise CRSError( - "Invalid ellipsoid name: {}".format( - pystrdecode(ellipsoid_name) - ) - ) + raise CRSError(f"Invalid ellipsoid name: {pystrdecode(ellipsoid_name)}") CRSError.clear() return Ellipsoid.create(context, ellipsoid_pj) @@ -1013,7 +986,7 @@ cdef class Ellipsoid(_CRSParts): _PJ_ELLPS_NAME_MAP.get(ellipsoid_name, ellipsoid_name) ] except KeyError: - raise CRSError("Invalid ellipsoid name: {}".format(ellipsoid_name)) + raise CRSError(f"Invalid ellipsoid name: {ellipsoid_name}") return CustomEllipsoid( name=ellipsoid_params["description"], semi_major_axis=ellipsoid_params["a"], @@ -1094,9 +1067,7 @@ cdef class PrimeMeridian(_CRSParts): if prime_meridian_pj == NULL: proj_context_destroy(context) - raise CRSError( - "Invalid authority or code ({0}, {1})".format(auth_name, code) - ) + raise CRSError(f"Invalid authority or code ({auth_name}, {code})") CRSError.clear() return PrimeMeridian.create(context, prime_meridian_pj) @@ -1151,9 +1122,7 @@ cdef class PrimeMeridian(_CRSParts): proj_destroy(prime_meridian_pj) proj_context_destroy(context) raise CRSError( - "Invalid prime meridian string: {}".format( - pystrdecode(prime_meridian_string) - ) + f"Invalid prime meridian string: {pystrdecode(prime_meridian_string)}" ) CRSError.clear() return PrimeMeridian.create(context, prime_meridian_pj) @@ -1261,9 +1230,7 @@ cdef class PrimeMeridian(_CRSParts): if prime_meridian_pj == NULL: proj_context_destroy(context) raise CRSError( - "Invalid prime meridian name: {}".format( - pystrdecode(prime_meridian_name) - ) + f"Invalid prime meridian name: {pystrdecode(prime_meridian_name)}" ) CRSError.clear() return PrimeMeridian.create(context, prime_meridian_pj) @@ -1361,9 +1328,7 @@ cdef class Datum(_CRSParts): if datum_pj == NULL: proj_context_destroy(context) - raise CRSError( - "Invalid authority or code ({0}, {1})".format(auth_name, code) - ) + raise CRSError(f"Invalid authority or code ({auth_name}, {code})") CRSError.clear() return Datum.create(context, datum_pj) @@ -1422,11 +1387,7 @@ cdef class Datum(_CRSParts): ): proj_destroy(datum_pj) proj_context_destroy(context) - raise CRSError( - "Invalid datum string: {}".format( - pystrdecode(datum_string) - ) - ) + raise CRSError(f"Invalid datum string: {pystrdecode(datum_string)}") CRSError.clear() return Datum.create(context, datum_pj) @@ -1496,11 +1457,7 @@ cdef class Datum(_CRSParts): ) if datum_pj == NULL: proj_context_destroy(context) - raise CRSError( - "Invalid datum name: {}".format( - pystrdecode(datum_name) - ) - ) + raise CRSError(f"Invalid datum name: {pystrdecode(datum_name)}") CRSError.clear() return Datum.create(context, datum_pj) @@ -1552,9 +1509,7 @@ cdef class Datum(_CRSParts): try: datum_name=_DATUM_NAME_MAP[datum_name.upper().replace(" ", "")] except KeyError: - raise CRSError( - "Invalid datum name: {}".format(datum_name) - ) + raise CRSError(f"Invalid datum name: {datum_name}") return Datum.from_name( datum_name=datum_name, auth_name=auth_name, @@ -1729,21 +1684,14 @@ cdef class Param: return param def __str__(self): - return "{auth_name}:{auth_code}".format(self.auth_name, self.auth_code) + return f"{self.auth_name}:{self.auth_code}" def __repr__(self): - return ("Param(name={name}, auth_name={auth_name}, code={code}, " - "value={value}, unit_name={unit_name}, " - "unit_auth_name={unit_auth_name}, unit_code={unit_code}, " - "unit_category={unit_category})").format( - name=self.name, - auth_name=self.auth_name, - code=self.code, - value=self.value, - unit_name=self.unit_name, - unit_auth_name=self.unit_auth_name, - unit_code=self.unit_code, - unit_category=self.unit_category, + return ( + f"Param(name={self.name}, auth_name={self.auth_name}, code={self.code}, " + f"value={self.value}, unit_name={self.unit_name}, " + f"unit_auth_name={self.unit_auth_name}, unit_code={self.unit_code}, " + f"unit_category={self.unit_category})" ) @@ -1816,17 +1764,11 @@ cdef class Grid: return self.full_name def __repr__(self): - return ("Grid(short_name={short_name}, full_name={full_name}, " - "package_name={package_name}, url={url}, " - "direct_download={direct_download}, open_license={open_license}, " - "available={available})").format( - short_name=self.short_name, - full_name=self.full_name, - package_name=self.package_name, - url=self.url, - direct_download=self.direct_download, - open_license=self.open_license, - available=self.available + return ( + f"Grid(short_name={self.short_name}, full_name={self.full_name}, " + f"package_name={self.package_name}, url={self.url}, " + f"direct_download={self.direct_download}, " + f"open_license={self.open_license}, available={self.available})" ) @@ -1962,9 +1904,7 @@ cdef class CoordinateOperation(_CRSParts): if coord_operation_pj == NULL: proj_context_destroy(context) - raise CRSError( - "Invalid authority or code ({0}, {1})".format(auth_name, code) - ) + raise CRSError(f"Invalid authority or code ({auth_name}, {code})") CRSError.clear() return CoordinateOperation.create(context, coord_operation_pj) @@ -2023,9 +1963,8 @@ cdef class CoordinateOperation(_CRSParts): proj_destroy(coord_operation_pj) proj_context_destroy(context) raise CRSError( - "Invalid coordinate operation string: {}".format( - pystrdecode(coordinate_operation_string) - ) + "Invalid coordinate operation string: " + f"{pystrdecode(coordinate_operation_string)}" ) CRSError.clear() return CoordinateOperation.create(context, coord_operation_pj) @@ -2138,9 +2077,8 @@ cdef class CoordinateOperation(_CRSParts): if coordinate_operation_pj == NULL: proj_context_destroy(context) raise CRSError( - "Invalid coordinate operation name: {}".format( - pystrdecode(coordinate_operation_name) - ) + "Invalid coordinate operation name: " + f"{pystrdecode(coordinate_operation_name)}" ) CRSError.clear() return CoordinateOperation.create(context, coordinate_operation_pj) @@ -2276,15 +2214,10 @@ cdef class CoordinateOperation(_CRSParts): def __repr__(self): return ( - "\n" - "Name: {name}\n" - "Method: {method_name}\n" - "Area of Use:\n{area_of_use}" - ).format( - type_name=self.type_name, - name=self.name, - method_name=self.method_name, - area_of_use=self.area_of_use or "- undefined", + f"\n" + f"Name: {self.name}\n" + f"Method: {self.method_name}\n" + f"Area of Use:\n{self.area_of_use or '- undefined'}" ) @@ -2335,11 +2268,10 @@ cdef class _CRS(Base): cstrencode(proj_string), ) if self.projobj == NULL: - raise CRSError( - "Invalid projection: {}".format(pystrdecode(proj_string))) + raise CRSError(f"Invalid projection: {pystrdecode(proj_string)}") # make sure the input is a CRS if not proj_is_crs(self.projobj): - raise CRSError("Input is not a CRS: {}".format(proj_string)) + raise CRSError(f"Input is not a CRS: {proj_string}") # set proj information self.srs = pystrdecode(proj_string) self._type = proj_get_type(self.projobj) diff --git a/pyproj/_geod.pyx b/pyproj/_geod.pyx index f4024934c..59fb5ab0a 100644 --- a/pyproj/_geod.pyx +++ b/pyproj/_geod.pyx @@ -5,10 +5,8 @@ cimport cython from pyproj.compat import cstrencode, pystrdecode from pyproj.exceptions import GeodError -geodesic_version_str = "{0}.{1}.{2}".format( - GEODESIC_VERSION_MAJOR, - GEODESIC_VERSION_MINOR, - GEODESIC_VERSION_PATCH +geodesic_version_str = ( + f"{GEODESIC_VERSION_MAJOR}.{GEODESIC_VERSION_MINOR}.{GEODESIC_VERSION_PATCH}" ) cdef class Geod: @@ -19,7 +17,7 @@ cdef class Geod: # convert 'a' only for initstring a_str = int(a) if a.is_integer() else a f_str = int(f) if f.is_integer() else f - self.initstring = pystrdecode(cstrencode("+a=%s +f=%s" % (a_str, f_str))) + self.initstring = pystrdecode(cstrencode(f"+a={a_str} +f={f_str}")) self.sphere = sphere self.b = b self.es = es @@ -316,7 +314,4 @@ cdef class Geod: return (polygon_area, polygon_perimeter) def __repr__(self): - return "{classname}({init!r})".format( - classname=self.__class__.__name__, - init=self.initstring, - ) + return f"{self.__class__.__name__}({self.initstring!r})" diff --git a/pyproj/_proj.pyx b/pyproj/_proj.pyx index 70426e628..a83c41751 100644 --- a/pyproj/_proj.pyx +++ b/pyproj/_proj.pyx @@ -11,11 +11,7 @@ from pyproj.compat import cstrencode, pystrdecode from pyproj.exceptions import ProjError # version number string for PROJ -proj_version_str = "{0}.{1}.{2}".format( - PROJ_VERSION_MAJOR, - PROJ_VERSION_MINOR, - PROJ_VERSION_PATCH -) +proj_version_str = f"{PROJ_VERSION_MAJOR}.{PROJ_VERSION_MINOR}.{PROJ_VERSION_PATCH}" Factors = namedtuple( @@ -83,7 +79,7 @@ cdef class _Proj: # initialize projection self.projobj = proj_create(self.context, projstring) if self.projobj is NULL: - raise ProjError("Invalid projection {}.".format(projstring)) + raise ProjError(f"Invalid projection {projstring}.") self.projobj_info = proj_pj_info(self.projobj) ProjError.clear() @@ -147,8 +143,9 @@ cdef class _Proj: projxyout = proj_trans(self.projobj, PJ_FWD, projlonlatin) errno = proj_errno(self.projobj) if errcheck and errno: - raise ProjError("proj error: {}".format( - pystrdecode(proj_errno_string(errno)))) + raise ProjError( + f"proj error: {pystrdecode(proj_errno_string(errno)))}" + ) elif errcheck: with gil: if ProjError.internal_proj_error is not None: @@ -223,8 +220,9 @@ cdef class _Proj: errno = proj_errno(self.projobj) if errcheck and errno: with gil: - raise ProjError("proj error: {}".format( - pystrdecode(proj_errno_string(errno)))) + raise ProjError( + f"proj error: {pystrdecode(proj_errno_string(errno))}" + ) elif errcheck: with gil: if ProjError.internal_proj_error is not None: @@ -324,8 +322,9 @@ cdef class _Proj: errno = proj_errno(self.projobj) if errcheck and errno: with gil: - raise ProjError("proj error: {}".format( - pystrdecode(proj_errno_string(errno)))) + raise ProjError( + f"proj error: {pystrdecode(proj_errno_string(errno))}" + ) if errno or invalid_coord: meridional_scale_buff.data[iii] = HUGE_VAL @@ -378,7 +377,7 @@ cdef class _Proj: ) def __repr__(self): - return "Proj('{srs}', preserve_units=True)".format(srs=self.srs) + return f"Proj('{self.srs}', preserve_units=True)" def _is_exact_same(self, _Proj other): return proj_is_equivalent_to( diff --git a/pyproj/_show_versions.py b/pyproj/_show_versions.py index 3683c4940..03faffb66 100644 --- a/pyproj/_show_versions.py +++ b/pyproj/_show_versions.py @@ -84,7 +84,7 @@ def get_version(module): def _print_info_dict(info_dict): """Print the information dictionary""" for key, stat in info_dict.items(): - print("{key:>10}: {stat}".format(key=key, stat=stat)) + print(f"{key:>10}: {stat}") def show_versions(): diff --git a/pyproj/_transformer.pyx b/pyproj/_transformer.pyx index 8b7d973a0..2ab39017d 100644 --- a/pyproj/_transformer.pyx +++ b/pyproj/_transformer.pyx @@ -166,7 +166,7 @@ cdef class _TransformerGroup: self._best_available = False warnings.warn( "Best transformation is not available due to missing " - "{!r}".format(coordinate_operation.grids[0]) + f"{coordinate_operation.grids[0]!r}" ) finally: if operation_factory_context != NULL: @@ -367,7 +367,7 @@ cdef class _Transformer(Base): proj_pipeline, ) if transformer.projobj is NULL: - raise ProjError("Invalid projection {}.".format(proj_pipeline)) + raise ProjError(f"Invalid projection {proj_pipeline}.") transformer._initialize_from_projobj() transformer._set_radians_io() transformer.is_pipeline = True @@ -484,8 +484,9 @@ cdef class _Transformer(Base): ) cdef int errno = proj_errno(self.projobj) if errcheck and errno: - raise ProjError("transform error: {}".format( - pystrdecode(proj_errno_string(errno)))) + raise ProjError( + f"transform error: {pystrdecode(proj_errno_string(errno))}" + ) elif errcheck and ProjError.internal_proj_error is not None: raise ProjError("transform error") @@ -583,8 +584,9 @@ cdef class _Transformer(Base): ) cdef int errno = proj_errno(self.projobj) if errcheck and errno: - raise ProjError("itransform error: {}".format( - pystrdecode(proj_errno_string(errno)))) + raise ProjError( + f"itransform error: {pystrdecode(proj_errno_string(errno))}" + ) elif errcheck and ProjError.internal_proj_error is not None: raise ProjError("itransform error") diff --git a/pyproj/crs/coordinate_operation.py b/pyproj/crs/coordinate_operation.py index a9ba7aeb8..fc1075c6a 100644 --- a/pyproj/crs/coordinate_operation.py +++ b/pyproj/crs/coordinate_operation.py @@ -210,7 +210,7 @@ def __new__( sweep_angle_axis = sweep_angle_axis.strip().upper() valid_sweep_axis = ("X", "Y") if sweep_angle_axis not in valid_sweep_axis: - raise CRSError("sweep_angle_axis only supports {}".format(valid_sweep_axis)) + raise CRSError(f"sweep_angle_axis only supports {valid_sweep_axis}") if latitude_natural_origin != 0: warnings.warn( @@ -223,9 +223,7 @@ def __new__( "$schema": "https://proj.org/schemas/v0.2/projjson.schema.json", "type": "Conversion", "name": "unknown", - "method": { - "name": "Geostationary Satellite (Sweep {})".format(sweep_angle_axis) - }, + "method": {"name": f"Geostationary Satellite (Sweep {sweep_angle_axis})"}, "parameters": [ { "name": "Satellite height", @@ -597,15 +595,10 @@ def __new__( # https://proj.org/operations/projections/cea.html proj_string = ( "+proj=cea " - "+lon_0={longitude_natural_origin} " - "+x_0={false_easting} " - "+y_0={false_northing} " - "+k_0={scale_factor_natural_origin}".format( - longitude_natural_origin=longitude_natural_origin, - false_easting=false_easting, - false_northing=false_northing, - scale_factor_natural_origin=scale_factor_natural_origin, - ) + f"+lon_0={longitude_natural_origin} " + f"+x_0={false_easting} " + f"+y_0={false_northing} " + f"+k_0={scale_factor_natural_origin}" ) if LooseVersion(proj_version_str) >= LooseVersion("6.3.1"): return cls.from_json( @@ -1208,9 +1201,7 @@ def __new__(cls, zone: str, hemisphere: str = "N"): hemisphere: str, optional Either N for North or S for South. Default is N. """ - return cls.from_name( - "UTM zone {zone}{hemisphere}".format(zone=zone, hemisphere=hemisphere) - ) + return cls.from_name(f"UTM zone {zone}{hemisphere}") class TransverseMercatorConversion(CoordinateOperation): diff --git a/pyproj/crs/crs.py b/pyproj/crs/crs.py index 12979a364..87283bf44 100644 --- a/pyproj/crs/crs.py +++ b/pyproj/crs/crs.py @@ -45,17 +45,17 @@ def _prepare_from_dict(projparams: dict, allow_json: bool = True) -> str: value = ",".join([str(val) for val in value]) # issue 183 (+ no_rot) if value is None or str(value) == "True": - pjargs.append("+{key}".format(key=key)) + pjargs.append(f"+{key}") elif str(value) == "False": pass else: - pjargs.append("+{key}={value}".format(key=key, value=value)) + pjargs.append(f"+{key}={value}") return _prepare_from_string(" ".join(pjargs)) def _prepare_from_string(in_crs_string: str) -> str: if not in_crs_string: - raise CRSError("CRS is empty or invalid: {!r}".format(in_crs_string)) + raise CRSError(f"CRS is empty or invalid: {in_crs_string!r}") elif "{" in in_crs_string: # may be json, try to decode it try: @@ -105,7 +105,7 @@ def _prepare_from_string(in_crs_string: str) -> str: def _prepare_from_authority(auth_name: str, auth_code: Union[str, int]): - return "{}:{}".format(auth_name, auth_code) + return f"{auth_name}:{auth_code}" def _prepare_from_epsg(auth_code: Union[str, int]): @@ -266,7 +266,7 @@ def __init__(self, projparams: Any = None, **kwargs) -> None: LENGTHUNIT["metre",1, ID["EPSG",9001]]]] >>> geod = crs.get_geod() - >>> "+a={:.0f} +f={:.8f}".format(geod.a, geod.f) + >>> f"+a={geod.a:.0f} +f={geod.f:.8f}" '+a=6378137 +f=0.00335281' >>> crs.is_projected True @@ -287,7 +287,7 @@ def __init__(self, projparams: Any = None, **kwargs) -> None: elif hasattr(projparams, "to_wkt"): projstring = projparams.to_wkt() # type: ignore else: - raise CRSError("Invalid CRS input: {!r}".format(projparams)) + raise CRSError(f"Invalid CRS input: {projparams!r}") if kwargs: projkwargs = _prepare_from_dict(kwargs, allow_json=False) @@ -347,7 +347,7 @@ def from_proj4(in_proj_string: str) -> "CRS": CRS """ if not is_proj(in_proj_string): - raise CRSError("Invalid PROJ string: {}".format(in_proj_string)) + raise CRSError(f"Invalid PROJ string: {in_proj_string}") return CRS(_prepare_from_string(in_proj_string)) @staticmethod @@ -367,7 +367,7 @@ def from_wkt(in_wkt_string: str) -> "CRS": CRS """ if not is_wkt(in_wkt_string): - raise CRSError("Invalid WKT string: {}".format(in_wkt_string)) + raise CRSError(f"Invalid WKT string: {in_wkt_string}") return CRS(_prepare_from_string(in_wkt_string)) @staticmethod @@ -656,9 +656,8 @@ def to_cf( if errcheck: if coordinate_operation: warnings.warn( - "Unsupported coordinate operation: {}".format( - coordinate_operation.method_name - ) + "Unsupported coordinate operation: " + f"{coordinate_operation.method_name}" ) else: warnings.warn("Coordinate operation not found.") @@ -737,9 +736,7 @@ def from_cf(in_cf: dict, errcheck=False) -> "CRS": try: conversion_method = _GRID_MAPPING_NAME_MAP[grid_mapping_name] except KeyError: - raise CRSError( - "Unsupported grid mapping name: {}".format(grid_mapping_name) - ) + raise CRSError(f"Unsupported grid mapping name: {grid_mapping_name}") projected_crs = ProjectedCRS( name=in_cf.get("projected_crs_name", "undefined"), conversion=conversion_method(in_cf), @@ -932,7 +929,7 @@ def __repr__(self) -> str: coordinate_system_name = str(self.coordinate_system) elif self.is_bound and self.source_crs: coordinate_system_name = str(self.source_crs.coordinate_system) - source_crs_repr = "Source CRS: {}\n".format(self.source_crs.name) + source_crs_repr = f"Source CRS: {self.source_crs.name}\n" else: coordinate_system_names = [] sub_crs_repr_list = ["Sub CRS:\n"] @@ -959,34 +956,21 @@ def __repr__(self) -> str: # get SRS representation srs_repr = self.to_string() srs_repr = srs_repr if len(srs_repr) <= 50 else " ".join([srs_repr[:50], "..."]) - string_repr = ( - "<{type_name}: {srs_repr}>\n" - "Name: {name}\n" - "Axis Info [{coordinate_system}]:\n" - "{axis_info_str}" + axis_info_str = axis_info_str or "- undefined\n" + return ( + f"<{self.type_name}: {srs_repr}>\n" + f"Name: {self.name}\n" + f"Axis Info [{coordinate_system_name or 'undefined'}]:\n" + f"{axis_info_str}" "Area of Use:\n" - "{area_of_use}\n" - "{coordinate_operation}" - "Datum: {datum}\n" - "- Ellipsoid: {ellipsoid}\n" - "- Prime Meridian: {prime_meridian}\n" - "{source_crs_repr}" - "{sub_crs_repr}" - ).format( - type_name=self.type_name, - srs_repr=srs_repr, - name=self.name, - axis_info_str=axis_info_str or "- undefined\n", - area_of_use=self.area_of_use or "- undefined", - coordinate_system=coordinate_system_name or "undefined", - coordinate_operation=coordinate_operation, - datum=self.datum, - ellipsoid=self.ellipsoid or "undefined", - prime_meridian=self.prime_meridian or "undefined", - source_crs_repr=source_crs_repr, - sub_crs_repr=sub_crs_repr, + f"{self.area_of_use or '- undefined'}\n" + f"{coordinate_operation}" + f"Datum: {self.datum}\n" + f"- Ellipsoid: {self.ellipsoid or 'undefined'}\n" + f"- Prime Meridian: {self.prime_meridian or 'undefined'}\n" + f"{source_crs_repr}" + f"{sub_crs_repr}" ) - return string_repr class GeographicCRS(CRS): diff --git a/pyproj/enums.py b/pyproj/enums.py index e6b168923..5caea79c4 100644 --- a/pyproj/enums.py +++ b/pyproj/enums.py @@ -17,10 +17,8 @@ def create(cls, item): if member.value == item: return member raise ValueError( - "Invalid value supplied '{}'. " - "Only {} are supported.".format( - item, tuple(version.value for version in cls) - ) + f"Invalid value supplied '{item}'. " + f"Only {tuple(version.value for version in cls)} are supported." ) diff --git a/pyproj/exceptions.py b/pyproj/exceptions.py index d9cde0117..906435407 100644 --- a/pyproj/exceptions.py +++ b/pyproj/exceptions.py @@ -11,10 +11,7 @@ class ProjError(RuntimeError): def __init__(self, error_message: str) -> None: 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, + f"{error_message}: (Internal Proj Error: {self.internal_proj_error})" ) ProjError.clear() super().__init__(error_message) diff --git a/pyproj/geod.py b/pyproj/geod.py index 5076dcf43..813055d32 100644 --- a/pyproj/geod.py +++ b/pyproj/geod.py @@ -82,13 +82,13 @@ def __init__(self, initstring: Optional[str] = None, **kwargs) -> None: >>> # compute forward and back azimuths, plus distance >>> # between Boston and Portland. >>> az12,az21,dist = g.inv(boston_lon,boston_lat,portland_lon,portland_lat) - >>> "%7.3f %6.3f %12.3f" % (az12,az21,dist) - '-66.531 75.654 4164192.708' + >>> f"{az12:.3f} {az21:.3f} {dist:.3f}" + '-66.531 75.654 4164192.708' >>> # compute latitude, longitude and back azimuth of Portland, >>> # given Boston lat/lon, forward azimuth and distance to Portland. >>> endlon, endlat, backaz = g.fwd(boston_lon, boston_lat, az12, dist) - >>> "%6.3f %6.3f %13.3f" % (endlat,endlon,backaz) - '45.517 -123.683 75.654' + >>> f"{endlat:.3f} {endlon:.3f} {backaz:.3f}" + '45.517 -123.683 75.654' >>> # compute the azimuths, distances from New York to several >>> # cities (pass a list) >>> lons1 = 3*[newyork_lon]; lats1 = 3*[newyork_lat] @@ -96,14 +96,14 @@ def __init__(self, initstring: Optional[str] = None, **kwargs) -> None: >>> lats2 = [boston_lat, portland_lat, london_lat] >>> az12,az21,dist = g.inv(lons1,lats1,lons2,lats2) >>> for faz, baz, d in list(zip(az12,az21,dist)): - ... "%7.3f %7.3f %9.3f" % (faz, baz, d) - ' 54.663 -123.448 288303.720' - '-65.463 79.342 4013037.318' - ' 51.254 -71.576 5579916.651' + ... f"{faz:7.3f} {baz:8.3f} {d:12.3f}" + ' 54.663 -123.448 288303.720' + '-65.463 79.342 4013037.318' + ' 51.254 -71.576 5579916.651' >>> g2 = Geod('+ellps=clrk66') # use proj4 style initialization string >>> az12,az21,dist = g2.inv(boston_lon,boston_lat,portland_lon,portland_lat) - >>> "%7.3f %6.3f %12.3f" % (az12,az21,dist) - '-66.531 75.654 4164192.708' + >>> f"{az12:.3f} {az21:.3f} {dist:.3f}" + '-66.531 75.654 4164192.708' """ # if initparams is a proj-type init string, # convert to dict. @@ -289,17 +289,17 @@ def npts( >>> portland_lat = 45.+(31./60.); portland_lon = -123.-(41./60.) >>> # find ten equally spaced points between Boston and Portland. >>> lonlats = g.npts(boston_lon,boston_lat,portland_lon,portland_lat,10) - >>> for lon,lat in lonlats: '%6.3f %7.3f' % (lat, lon) - '43.528 -75.414' - '44.637 -79.883' - '45.565 -84.512' - '46.299 -89.279' - '46.830 -94.156' - '47.149 -99.112' - '47.251 -104.106' - '47.136 -109.100' - '46.805 -114.051' - '46.262 -118.924' + >>> for lon,lat in lonlats: f'{lat:.3f} {lon:.3f}' + '43.528 -75.414' + '44.637 -79.883' + '45.565 -84.512' + '46.299 -89.279' + '46.830 -94.156' + '47.149 -99.112' + '47.251 -104.106' + '47.136 -109.100' + '46.805 -114.051' + '46.262 -118.924' >>> # test with radians=True (inputs/outputs in radians, not degrees) >>> import math >>> dg2rad = math.radians(1.) @@ -312,17 +312,17 @@ def npts( ... 10, ... radians=True ... ) - >>> for lon,lat in lonlats: '%6.3f %7.3f' % (rad2dg*lat, rad2dg*lon) - '43.528 -75.414' - '44.637 -79.883' - '45.565 -84.512' - '46.299 -89.279' - '46.830 -94.156' - '47.149 -99.112' - '47.251 -104.106' - '47.136 -109.100' - '46.805 -114.051' - '46.262 -118.924' + >>> for lon,lat in lonlats: f'{rad2dg*lat:.3f} {rad2dg*lon:.3f}' + '43.528 -75.414' + '44.637 -79.883' + '45.565 -84.512' + '46.299 -89.279' + '46.830 -94.156' + '47.149 -99.112' + '47.251 -104.106' + '47.136 -109.100' + '46.805 -114.051' + '46.262 -118.924' Parameters ---------- @@ -361,7 +361,7 @@ def line_length(self, lons: Any, lats: Any, radians: bool = False) -> float: >>> lons = [-74, -102, -102, -131, -163, 163, 172, 140, 113, ... 88, 59, 25, -4, -14, -33, -46, -61] >>> total_length = geod.line_length(lons, lats) - >>> "{:.3f}".format(total_length) + >>> f"{total_length:.3f}" '14259605.611' @@ -395,7 +395,7 @@ def line_lengths(self, lons: Any, lats: Any, radians: bool = False) -> Any: >>> lats = [-72.9, -71.9, -74.9] >>> lons = [-74, -102, -102] >>> for line_length in geod.line_lengths(lons, lats): - ... "{:.3f}".format(line_length) + ... f"{line_length:.3f}" '943065.744' '334805.010' @@ -446,7 +446,7 @@ def polygon_area_perimeter( >>> lons = [-74, -102, -102, -131, -163, 163, 172, 140, 113, ... 88, 59, 25, -4, -14, -33, -46, -61] >>> poly_area, poly_perimeter = geod.polygon_area_perimeter(lons, lats) - >>> "{:.1f} {:.1f}".format(poly_area, poly_perimeter) + >>> f"{poly_area:.1f} {poly_perimeter:.1f}" '13376856682207.4 14710425.4' @@ -485,7 +485,7 @@ def geometry_length(self, geometry, radians: bool = False) -> float: >>> from shapely.geometry import Point, LineString >>> line_string = LineString([Point(1, 2), Point(3, 4)]) >>> geod = Geod(ellps="WGS84") - >>> "{:.3f}".format(geod.geometry_length(line_string)) + >>> f"{geod.geometry_length(line_string):.3f}" '313588.397' Parameters @@ -549,7 +549,7 @@ def geometry_area_perimeter( ... holes=[LineString([Point(1, 2), Point(3, 4), Point(5, 2)])], ... ) ... ) - >>> "{:.3f} {:.3f}".format(poly_area, poly_perimeter) + >>> f"{poly_area:.3f} {poly_perimeter:.3f}" '-944373881400.339 3979008.036' @@ -601,9 +601,7 @@ def __repr__(self) -> str: # self.sphere is True when self.f is zero or very close to # zero (0), so prevent divide by zero. if self.b == b or (not self.sphere and (1.0 / self.f) == rf): - return "{classname}(ellps={ellps!r})" "".format( - classname=self.__class__.__name__, ellps=ellps - ) + return f"{self.__class__.__name__}(ellps={ellps!r})" # no ellipse name found, call super class return super().__repr__() diff --git a/pyproj/proj.py b/pyproj/proj.py index 3f71cd823..a44e9bae4 100644 --- a/pyproj/proj.py +++ b/pyproj/proj.py @@ -98,10 +98,10 @@ def __init__( >>> # test data with radian inputs >>> p1 = Proj("epsg:4214") >>> x1, y1 = p1(116.366, 39.867) - >>> '{:.3f} {:.3f}'.format(x1, y1) + >>> f'{x1:.3f} {y1:.3f}' '116.366 39.867' >>> x2, y2 = p1(x1, y1, inverse=True) - >>> '{:.3f} {:.3f}'.format(x2, y2) + >>> f'{x2:.3f} {y2:.3f}' '116.366 39.867' """ self.crs = CRS.from_user_input(projparams, **kwargs) @@ -285,7 +285,7 @@ def __reduce__(self) -> Tuple[Type["Proj"], Tuple[str]]: return self.__class__, (self.crs.srs,) def __repr__(self) -> str: - return "Proj('{srs}', preserve_units=True)".format(srs=self.srs) + return f"Proj('{self.srs}', preserve_units=True)" def __eq__(self, other: Any) -> bool: if not isinstance(other, Proj): diff --git a/pyproj/transformer.py b/pyproj/transformer.py index c923fc788..896dc457f 100644 --- a/pyproj/transformer.py +++ b/pyproj/transformer.py @@ -107,13 +107,9 @@ def best_available(self) -> bool: def __repr__(self) -> str: return ( - "\n" - "- transformers: {transformers}\n" - "- unavailable_operations: {unavailable_operations}" - ).format( - best_available=self.best_available, - transformers=len(self.transformers), - unavailable_operations=len(self.unavailable_operations), + f"\n" + f"- transformers: {len(self.transformers)}\n" + f"- unavailable_operations: {len(self.unavailable_operations)}" ) @@ -378,7 +374,7 @@ def transform( >>> from pyproj import Transformer >>> transformer = Transformer.from_crs("epsg:4326", "epsg:3857") >>> x3, y3 = transformer.transform(33, 98) - >>> "%.3f %.3f" % (x3, y3) + >>> f"{x3:.3f} {y3:.3f}" '10909310.098 3895303.963' >>> pipeline_str = ( ... "+proj=pipeline +step +proj=longlat +ellps=WGS84 " @@ -386,7 +382,7 @@ def transform( ... ) >>> pipe_trans = Transformer.from_pipeline(pipeline_str) >>> xt, yt = pipe_trans.transform(2.1, 0.001) - >>> "%.3f %.3f" % (xt, yt) + >>> f"{xt:.3f} {yt:.3f}" '2.100 0.001' >>> transproj = Transformer.from_crs( ... {"proj":'geocent', "ellps":'WGS84', "datum":'WGS84'}, @@ -399,7 +395,7 @@ def transform( ... 3895878.820, ... radians=True, ... ) - >>> "%.3f %.3f %.3f" % (xpj, ypj, zpj) + >>> f"{xpj:.3f} {ypj:.3f} {zpj:.3f}" '-2.137 0.661 -20.531' >>> transprojr = Transformer.from_crs( ... "EPSG:4326", @@ -407,11 +403,11 @@ def transform( ... always_xy=True, ... ) >>> xpjr, ypjr, zpjr = transprojr.transform(xpj, ypj, zpj, radians=True) - >>> "%.3f %.3f %.3f" % (xpjr, ypjr, zpjr) + >>> f"{xpjr:.3f} {ypjr:.3f} {zpjr:.3f}" '-2704026.010 -4253051.810 3895878.820' >>> transformer = Transformer.from_proj("epsg:4326", 4326, skip_equivalent=True) >>> xeq, yeq = transformer.transform(33, 98) - >>> "%.0f %.0f" % (xeq, yeq) + >>> f"{xeq:.0f} {yeq:.0f}" '33 98' """ @@ -645,13 +641,9 @@ def __str__(self) -> str: def __repr__(self) -> str: return ( - "<{type_name}: {name}>\nDescription: {description}\n" - "Area of Use:\n{area_of_use}" - ).format( - type_name=self._transformer.type_name, - name=self.name, - description=self.description, - area_of_use=self.area_of_use or "- undefined", + f"<{self._transformer.type_name}: {self.name}>\n" + f"Description: {self.description}\n" + f"Area of Use:\n{self.area_of_use or '- undefined'}" ) def __eq__(self, other: Any) -> bool: diff --git a/setup.py b/setup.py index bab7a396d..f310e6550 100644 --- a/setup.py +++ b/setup.py @@ -22,11 +22,9 @@ def check_proj_version(proj_dir): proj_version = parse_version(proj_ver_bytes) if proj_version < PROJ_MIN_VERSION: sys.exit( - "ERROR: Minimum supported proj version is {}, installed " - "version is {}. For more information see: " - "https://pyproj4.github.io/pyproj/stable/installation.html".format( - PROJ_MIN_VERSION, proj_version - ) + f"ERROR: Minimum supported proj version is {PROJ_MIN_VERSION}, installed " + f"version is {proj_version}. For more information see: " + "https://pyproj4.github.io/pyproj/stable/installation.html" ) return proj_version @@ -39,7 +37,7 @@ def get_proj_dir(): proj_dir = os.environ.get("PROJ_DIR") if proj_dir is None and os.path.exists(INTERNAL_PROJ_DIR): proj_dir = INTERNAL_PROJ_DIR - print("Internally compiled directory being used {}.".format(INTERNAL_PROJ_DIR)) + print(f"Internally compiled directory being used {INTERNAL_PROJ_DIR}.") elif proj_dir is None and not os.path.exists(INTERNAL_PROJ_DIR): proj = find_executable("proj", path=sys.prefix) if proj is None: @@ -54,7 +52,7 @@ def get_proj_dir(): elif proj_dir is not None and os.path.exists(proj_dir): print("PROJ_DIR is set, using existing proj4 installation..\n") else: - sys.exit("ERROR: Invalid path for PROJ_DIR {}".format(proj_dir)) + sys.exit(f"ERROR: Invalid path for PROJ_DIR {proj_dir}") # check_proj_version check_proj_version(proj_dir) @@ -168,7 +166,7 @@ def get_extension_modules(): Extension("pyproj._list", ["pyproj/_list.pyx"], **ext_options), ], quiet=True, - **get_cythonize_options() + **get_cythonize_options(), ) @@ -229,7 +227,6 @@ def get_long_description(): "Development Status :: 4 - Beta", "Intended Audience :: Science/Research", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", @@ -239,7 +236,7 @@ def get_long_description(): "Operating System :: OS Independent", ], packages=["pyproj", "pyproj.crs"], - python_requires=">=3.5", + python_requires=">=3.6", ext_modules=get_extension_modules(), package_data=get_package_data(), ) diff --git a/test/crs/test_crs.py b/test/crs/test_crs.py index 9ea5a7d9f..89fe743c6 100644 --- a/test/crs/test_crs.py +++ b/test/crs/test_crs.py @@ -434,9 +434,9 @@ def test_compound_crs(): def test_ellipsoid(): crs1 = CRS.from_epsg(4326) - assert "{:.3f}".format(crs1.ellipsoid.inverse_flattening) == "298.257" - assert "{:.3f}".format(crs1.ellipsoid.semi_major_metre) == "6378137.000" - assert "{:.3f}".format(crs1.ellipsoid.semi_minor_metre) == "6356752.314" + assert f"{crs1.ellipsoid.inverse_flattening:.3f}" == "298.257" + assert f"{crs1.ellipsoid.semi_major_metre:.3f}" == "6378137.000" + assert f"{crs1.ellipsoid.semi_minor_metre:.3f}" == "6356752.314" def test_ellipsoid__semi_minor_not_computed(): diff --git a/test/test_doctest_wrapper.py b/test/test_doctest_wrapper.py index 996281c0d..8bd038819 100644 --- a/test/test_doctest_wrapper.py +++ b/test/test_doctest_wrapper.py @@ -43,4 +43,4 @@ def test_doctests(): # if the below line fails, doctests have failed assert ( failure_count == expected_failure_count - ), "{0} of the doctests in " "lib/pyproj/__init__.py failed".format(failure_count) + ), f"{failure_count} of the doctests failed" diff --git a/test/test_proj.py b/test/test_proj.py index 6d6288522..eb2b85bfa 100644 --- a/test/test_proj.py +++ b/test/test_proj.py @@ -232,7 +232,7 @@ def test_ellps_name_round_trip(self): if ellps_name in ("NWL9D", "WGS66"): continue p = Geod(ellps=ellps_name) - expected = "Geod(ellps='{0}')".format(ellps_name) + expected = f"Geod(ellps='{ellps_name}')" self.assertEqual(repr(p), expected) diff --git a/test/test_transformer.py b/test/test_transformer.py index d4e187fb1..e04b4f57c 100644 --- a/test/test_transformer.py +++ b/test/test_transformer.py @@ -23,7 +23,7 @@ def test_tranform_wgs84_to_custom(): lat, lon = 51.04715, 3.23406 with pytest.warns(DeprecationWarning): xx, yy = pyproj.transform(wgs84, custom_proj, lon, lat) - assert "{:.3f} {:.3f}".format(xx, yy) == "212.623 4604.975" + assert f"{xx:.3f} {yy:.3f}" == "212.623 4604.975" def test_transform_wgs84_to_alaska(): @@ -33,7 +33,7 @@ def test_transform_wgs84_to_alaska(): test = (-179.72638, 49.752533) with pytest.warns(DeprecationWarning): xx, yy = pyproj.transform(lat_lon_proj, alaska_aea_proj, *test) - assert "{:.3f} {:.3f}".format(xx, yy) == "-1824924.495 330822.800" + assert f"{xx:.3f} {yy:.3f}" == "-1824924.495 330822.800" def test_illegal_transformation():