Repository: SciTools/cartopy

Issue:
Packaging dependency requirement
### Description

`packaging` is only listed as a test dependency, but we are now version gating in the main importable code section. We should either figure out a different way to do the version checks within the code or add it as a primary dependency.

ping @rcomer it looks like this came in these two PRs: #2213, #2215



Discussion:

Resolving patch:
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -4,35 +4,11 @@
 # See COPYING and COPYING.LESSER in the root of the repository for full
 # licensing details.
 
-# NOTE: This file must remain Python 2 compatible for the foreseeable future,
-# to ensure that we error out properly for people with outdated setuptools
-# and/or pip.
-import sys
-
-
-PYTHON_MIN_VERSION = (3, 9)
-
-if sys.version_info < PYTHON_MIN_VERSION:
-    error = """
-Beginning with Cartopy 0.22, Python {} or above is required.
-You are using Python {}.
-
-This may be due to an out of date pip.
-
-Make sure you have pip >= 9.0.1.
-""".format('.'.join(str(n) for n in PYTHON_MIN_VERSION),
-           '.'.join(str(n) for n in sys.version_info[:3]))
-    sys.exit(error)
-
-
-from collections import defaultdict
 import os
 from pathlib import Path
-import subprocess
-from sysconfig import get_config_var
-import warnings
 
-from setuptools import Extension, find_packages, setup
+import numpy as np
+from setuptools import Extension, setup
 
 
 # The existence of a PKG-INFO directory is enough to tell us whether this is a
@@ -41,176 +17,40 @@
 IS_SDIST = (HERE / 'PKG-INFO').exists()
 FORCE_CYTHON = os.environ.get('FORCE_CYTHON', False)
 
-if not IS_SDIST or FORCE_CYTHON:
+USE_CYTHON = not IS_SDIST or FORCE_CYTHON
+if USE_CYTHON:
     import Cython
     if Cython.__version__ < '0.29':
         raise ImportError(
             "Cython 0.29+ is required to install cartopy from source.")
+    ext = '.pyx'
+else:
+    ext = '.cpp'
 
-    from Cython.Distutils import build_ext as cy_build_ext
-
-
-try:
-    import numpy as np
-except ImportError:
-    raise ImportError('NumPy 1.21+ is required to install cartopy.')
-
-
-def file_walk_relative(root):
-    """
-    Return a list of files from the top of the tree, removing
-    the lib/cartopy prefix from the resulting paths.
-
-    """
-    return [str(p.relative_to(Path('lib') / 'cartopy'))
-            for p in root.glob("**/*")]
-
-
-# Dependency checks
-# =================
-
-# Python dependencies
-extras_require = {}
-for name in (HERE / 'requirements').iterdir():
-    with open(name) as fh:
-        section, ext = name.stem, name.suffix
-        extras_require[section] = []
-        for line in fh:
-            if line.startswith('#'):
-                pass
-            elif line.startswith('-'):
-                pass
-            else:
-                extras_require[section].append(line.strip())
-install_requires = extras_require.pop('default')
-tests_require = extras_require.get('tests', [])
-
-# General extension paths
-if sys.platform.startswith('win'):
-    def get_config_var(name):
-        return '.'
-include_dir = get_config_var('INCLUDEDIR')
-library_dir = get_config_var('LIBDIR')
-extra_extension_args = defaultdict(list)
-if not sys.platform.startswith('win'):
-    extra_extension_args["runtime_library_dirs"].append(
-        get_config_var('LIBDIR')
-    )
-
-# Description
-# ===========
-with open(HERE / 'README.md') as fh:
-    description = ''.join(fh.readlines())
-
-
-cython_coverage_enabled = os.environ.get('CYTHON_COVERAGE', None)
-if cython_coverage_enabled:
-    extra_extension_args["define_macros"].append(
-        ('CYTHON_TRACE_NOGIL', '1')
-    )
+# Macros to enable Cython coverage
+define_macros = []
+if os.environ.get('CYTHON_COVERAGE'):
+    define_macros.append(('CYTHON_TRACE_NOGIL', '1'))
 
 extensions = [
     Extension(
         'cartopy.trace',
-        ['lib/cartopy/trace.pyx'],
-        include_dirs=[include_dir, './lib/cartopy', np.get_include()],
+        [f'lib/cartopy/trace{ext}'],
+        include_dirs=[np.get_include()],
         language='c++',
-        **extra_extension_args),
+        define_macros=define_macros),
 ]
 
-
-if cython_coverage_enabled:
+if USE_CYTHON:
     # We need to explicitly cythonize the extension in order
     # to control the Cython compiler_directives.
     from Cython.Build import cythonize
-
-    directives = {'linetrace': True,
-                  'binding': True}
-    extensions = cythonize(extensions, compiler_directives=directives)
-
-
-def decythonize(extensions, **_ignore):
-    # Remove pyx sources from extensions.
-    # Note: even if there are changes to the pyx files, they will be ignored.
-    for extension in extensions:
-        sources = []
-        for sfile in extension.sources:
-            spath = Path(sfile)
-            ext = spath.suffix
-            if ext in ('.pyx',):
-                if extension.language == 'c++':
-                    ext = '.cpp'
-                else:
-                    ext = '.c'
-                sfile = str(spath.with_suffix(ext))
-            sources.append(sfile)
-        extension.sources[:] = sources
-    return extensions
+    compiler_directives = {"profile": True, "linetrace": True}
+    extensions = cythonize(extensions, compiler_directives=compiler_directives)
 
 
-if IS_SDIST and not FORCE_CYTHON:
-    extensions = decythonize(extensions)
-    cmdclass = {}
-else:
-    cmdclass = {'build_ext': cy_build_ext}
-
-base_path = Path('lib') / 'cartopy'
-package_data = (
-    file_walk_relative(base_path / 'tests' / 'mpl' / 'baseline_images')
-    + file_walk_relative(base_path / 'data')
-    + file_walk_relative(base_path / 'tests' / 'lakes_shapefile')
-    + ['io/srtm.npz'])
-
 # Main setup
 # ==========
 setup(
-    name='Cartopy',
-    url='https://scitools.org.uk/cartopy/docs/latest/',
-    download_url='https://github.com/SciTools/cartopy',
-    author='UK Met Office',
-    description='A cartographic python library with Matplotlib support for '
-                'visualisation',
-    long_description=description,
-    long_description_content_type='text/markdown',
-    license="LGPLv3",
-    keywords="cartography map transform projection proj proj.4 geos shapely "
-             "shapefile",
-
-    install_requires=install_requires,
-    extras_require=extras_require,
-    tests_require=tests_require,
-
-    use_scm_version={
-        'write_to': 'lib/cartopy/_version.py',
-    },
-
-    packages=find_packages("lib"),
-    package_dir={'': 'lib'},
-    package_data={'cartopy': package_data},
-
-    scripts=['tools/cartopy_feature_download.py'],
     ext_modules=extensions,
-    cmdclass=cmdclass,
-    python_requires='>=' + '.'.join(str(n) for n in PYTHON_MIN_VERSION),
-    classifiers=[
-            'Development Status :: 4 - Beta',
-            'Framework :: Matplotlib',
-            'License :: OSI Approved :: GNU Lesser General Public License v3 '
-            'or later (LGPLv3+)',
-            'Operating System :: MacOS :: MacOS X',
-            'Operating System :: Microsoft :: Windows',
-            'Operating System :: POSIX',
-            'Operating System :: POSIX :: AIX',
-            'Operating System :: POSIX :: Linux',
-            'Programming Language :: C++',
-            'Programming Language :: Python',
-            'Programming Language :: Python :: 3',
-            'Programming Language :: Python :: 3.9',
-            'Programming Language :: Python :: 3.10',
-            'Programming Language :: Python :: 3.11',
-            'Programming Language :: Python :: 3 :: Only',
-            'Topic :: Scientific/Engineering',
-            'Topic :: Scientific/Engineering :: GIS',
-            'Topic :: Scientific/Engineering :: Visualization',
-          ],
 )


Test patch:
diff --git a/requirements/tests.txt b/requirements/tests.txt
deleted file mode 100644
--- a/requirements/tests.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-packaging>=20
-pytest>=5.1.2
-pytest-mpl>=0.11