Repository: drivendataorg/cloudpathlib (language: python)

Issue:
Updates to release v.0.18.0
Version, changes, etc.

Note: Planning to have this as the last Python 3.7 release and follow it with a PR to drop 3.7.
Add lower bound to boto3 dependency to make resolution smoother
See this poetry issue for discussion: https://github.com/python-poetry/poetry/issues/8799#issuecomment-1858394394

Need to figure out what a reasonable minimum for `boto3` is first.


Discussion / hints:

From reading that thread, I'm not convinced that it makes sense for us to put a lower bound on boto3 or botocore. Someone might genuinely need an older version of boto3 or botocore, or someone might have another dependency that might have a ceiling on boto3 or botocore, and this would be an artificial constraint that prevents resolution.

It seems like the underlying issue is that botocore way overdoes it on "continuous" releases—they've got 1,800+ versions available on PyPI—and this can cause degenerately inefficient behavior in Poetry's dependency resolver. 

Two things that feel like more appropriate solutions to me would be:

1. Poetry figures out how to have their dependency resolver handle this case, since botocore is a common dependency and this problem must show up a lot
2. botocore makes itself more resolver-friendly by [yanking](https://pypi.org/help/#yanked) a lot of their old releases. This means those versions are still available but get ignored by resolvers.

IMO, (2) is the most sensible solution since this is ultimately a problem that is specific to botocore that they themselves have caused. I recognize that I'm shifting responsibility here from us to other projects, but I don't think us (or other consumers of botocore) artificially introducing a floor on boto3/botocore is a reasonable solution. 
Agreed on all points

> artificially introducing a floor on boto3/botocore is a reasonable solution.

I guess I wonder if, for example, there's a set of versions that are purely incompatible with the versions of Python we support so we could set a lower bound that's not an artificial floor, but is an actual compatibility floor.

Fix patch:
diff --git a/HISTORY.md b/HISTORY.md
index a1d62681..75f949aa 100644
--- a/HISTORY.md
+++ b/HISTORY.md
@@ -1,6 +1,11 @@
 # cloudpathlib Changelog
 
+## UNRELEASED
+
+ - Drop support for Python 3.7; pin minimal `boto3` version to Python 3.8+ versions. (PR [#407](https://github.com/drivendataorg/cloudpathlib/pull/407))
+
 ## 0.18.0 (2024-02-25)
+
 - Implement sliced downloads in GSClient. (Issue [#387](https://github.com/drivendataorg/cloudpathlib/issues/387), PR [#389](https://github.com/drivendataorg/cloudpathlib/pull/389))
 - Implement `as_url` with presigned parameter for all backends. (Issue [#235](https://github.com/drivendataorg/cloudpathlib/issues/235), PR [#236](https://github.com/drivendataorg/cloudpathlib/pull/236))
 - Stream to and from Azure Blob Storage. (PR [#403](https://github.com/drivendataorg/cloudpathlib/pull/403))
diff --git a/pyproject.toml b/pyproject.toml
index 0fb3942c..1b37b976 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -21,23 +21,21 @@ classifiers = [
   "License :: OSI Approved :: MIT License",
   "Operating System :: OS Independent",
   "Programming Language :: Python :: 3",
-  "Programming Language :: Python :: 3.7",
   "Programming Language :: Python :: 3.8",
   "Programming Language :: Python :: 3.9",
   "Programming Language :: Python :: 3.10",
   "Programming Language :: Python :: 3.11",
   "Programming Language :: Python :: 3.12",
 ]
-requires-python = ">=3.7"
+requires-python = ">=3.8"
 dependencies = [
-  "importlib_metadata ; python_version < '3.8'",
   "typing_extensions>4 ; python_version < '3.11'",
 ]
 
 [project.optional-dependencies]
 azure = ["azure-storage-blob>=12"]
 gs = ["google-cloud-storage"]
-s3 = ["boto3"]
+s3 = ["boto3>=1.34.0"]
 all = ["cloudpathlib[azure]", "cloudpathlib[gs]", "cloudpathlib[s3]"]
 
 
@@ -50,7 +48,7 @@ all = ["cloudpathlib[azure]", "cloudpathlib[gs]", "cloudpathlib[s3]"]
 
 [tool.black]
 line-length = 99
-target-version = ['py37', 'py38', 'py39', 'py310', 'py311', 'py312']
+target-version = ['py38', 'py39', 'py310', 'py311', 'py312']
 include = '\.pyi?$|\.ipynb$'
 extend-exclude = '''
 /(


Test patch:
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 708bf4ad..1a33c5c4 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -42,7 +42,7 @@ jobs:
     strategy:
       matrix:
         os: [ubuntu-latest, macos-latest, windows-latest]
-        python-version: [3.7, 3.8, 3.9, "3.10", "3.11", "3.12"]
+        python-version: [3.8, 3.9, "3.10", "3.11", "3.12"]
 
     steps:
       - uses: actions/checkout@v3