Repository: getmoto/moto

Issue:
Moto's dependencies are locked to specific versions, makes it hard to install
As of https://github.com/spulec/moto/commit/00134d2df37bb4dcd5f447ef951d383bfec0903c some of the dependencies in `setup.py` are specified to exact (and outdated) versions. This makes it hard to install moto.

For example `more-itertools==5.0.0` is now over two years old, they're now on version 8.2... I am using version 8.2 in my project. I can no longer update moto to the latest on master in my project without doing some hackage to force my package manager (poetry) to ignore the dependency on _exactly_ 5.0.0

More details here python-poetry/poetry#697

Would moving python 2 support to a separate branch be a possibility? Or doing a version check on major python version in setup.py so there can effectively be a `install_requires_py2` and a `install_requires_py3` ?


Discussion:
Thanks for raising this @mfogel.
A version check in setup.py sounds like the best way forward IMO. 

Do you have an opinion on the best way to handle this @spulec ?
Hi, this also affects me. I can help if needed  to implement this.
I'm also wondering why support Python 2?
I'm also affected by this.

I think the current solution (apply a version pin on a dependency) is worse than the problem itself (the dependency does not support Python 2). I can think of several alternatives that are better in my opinion:

1. Drop moto support for Python 2.7 (that version of Python is no longer officially supported as of Jan 2020). You probably have lots of Py2.7 that won't be too happy with this, but they can continue to use previous versions of moto by applying a version pin on their side. You'll find that moving away from Py2.7 simplifies life for your developers and maintainers significantly.
2. Pin conditionally. So, if the user is running Py2.7, then they must have more-itertools version 5.0.0 or below.
3. Remove the pin. Let the user deal with it.

Can anyone think of other solutions?
Version check in setup.py sounds good to me.


@spulec Will you accept PRs, or do you prefer to deal with this yourself?
PR's are always welcome, @mpenkov!

Resolving patch:
diff --git a/moto/s3/models.py b/moto/s3/models.py
--- a/moto/s3/models.py
+++ b/moto/s3/models.py
@@ -1370,7 +1370,7 @@ def set_key_tags(self, key, tags, key_name=None):
             raise MissingKey(key_name)
         self.tagger.delete_all_tags_for_resource(key.arn)
         self.tagger.tag_resource(
-            key.arn, [{"Key": key, "Value": value} for key, value in tags.items()],
+            key.arn, [{"Key": k, "Value": v} for (k, v) in tags.items()],
         )
         return key
 
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -8,6 +8,8 @@
 from setuptools import setup, find_packages
 import sys
 
+PY2 = sys.version_info[0] == 2
+
 # Borrowed from pip at https://github.com/pypa/pip/blob/62c27dee45625e1b63d1e023b0656310f276e050/setup.py#L11-L15
 here = os.path.abspath(os.path.dirname(__file__))
 
@@ -28,8 +30,6 @@ def get_version():
 
 
 install_requires = [
-    "setuptools==44.0.0",
-    "Jinja2<3.0.0,>=2.10.1",
     "boto>=2.36.0",
     "boto3>=1.9.201",
     "botocore>=1.12.201",
@@ -42,18 +42,48 @@ def get_version():
     "pytz",
     "python-dateutil<3.0.0,>=2.1",
     "python-jose<4.0.0",
-    "mock<=3.0.5",
     "docker>=2.5.1",
     "jsondiff>=1.1.2",
     "aws-xray-sdk!=0.96,>=0.93",
     "responses>=0.9.0",
     "idna<3,>=2.5",
     "cfn-lint>=0.4.0",
-    "sshpubkeys>=3.1.0,<4.0",
-    "zipp==0.6.0",
-    "more-itertools==5.0.0"
+    "MarkupSafe<2.0",  # This is a Jinja2 dependency, 2.0.0a1 currently seems broken
 ]
 
+#
+# Avoid pins where they are not necessary.  These pins were introduced by the
+# following commit for Py2 compatibility.  They are not required for non-Py2
+# users.
+#
+#   https://github.com/mpenkov/moto/commit/00134d2df37bb4dcd5f447ef951d383bfec0903c
+#
+if PY2:
+    install_requires += [
+        #
+        # This is an indirect dependency. Version 5.0.0 claims to be for
+        # Py2.6+, but it really isn't.
+        #
+        # https://github.com/jaraco/configparser/issues/51
+        #
+        "configparser<5.0",
+        "Jinja2<3.0.0,>=2.10.1",
+        "mock<=3.0.5",
+        "more-itertools==5.0.0",
+        "setuptools==44.0.0",
+        "sshpubkeys>=3.1.0,<4.0",
+        "zipp==0.6.0",
+    ]
+else:
+    install_requires += [
+        "Jinja2>=2.10.1",
+        "mock",
+        "more-itertools",
+        "setuptools",
+        "sshpubkeys>=3.1.0",
+        "zipp",
+    ]
+
 extras_require = {
     'server': ['flask'],
 }


Test patch: