internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: docker/docker-py

Issue:
Installed through dependencies "websocket" library doesn't work with Python 3
During `pip install docker-py` with Python 3 I'm getting following error:

```
  Running setup.py install for websocket-client
    changing mode of build/scripts-3.3/wsdump.py from 644 to 755
      File "/home/bob/env/lib/python3.3/site-packages/websocket.py", line 769
        except Exception, e:
                        ^
    SyntaxError: invalid syntax
```

Looks like this error is ignored and actually docker finishes it's installation and works afterwards, but if docker-py uses websocket library it's usage will fail.

According to websocket docs they have separate branch for Python 3: https://github.com/liris/websocket-client/tree/py3



Discussion:
I'm not sure there is much we can do here. I don't think there is a way to specify different dependencies based on the Python version with `pip`/`requirements.txt`.


Resolving patch:
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -1,12 +1,18 @@
 #!/usr/bin/env python
 import os
+import sys
 from setuptools import setup
 
 ROOT_DIR = os.path.dirname(__file__)
 SOURCE_DIR = os.path.join(ROOT_DIR)
 
+if sys.version_info[0] == 3:
+    requirements_file = './requirements3.txt'
+else:
+    requirements_file = './requirements.txt'
+
 test_requirements = []
-with open('./requirements.txt') as requirements_txt:
+with open(requirements_file) as requirements_txt:
     requirements = [line for line in requirements_txt]
 
 setup(


Test patch:
Repository: docker/docker-py

Issue:
--dns-search support
Looking at the CLI reference, I see that the docker run command has an option called --dns-search: http://docs.docker.io/reference/commandline/cli/#run

Judging from the README and a glance at the code, I see that the create_container function takes a dns kwarg, but I'm assuming that's the same as the docker run --dns flag. Is this missing from docker-py, or is there some way to do this that I'm missing?

thanks



Discussion:
Right on all accounts! It should be relatively easy to add, do you want to take a crack at it?

Thanks for confirming. I don't think I'll have a chance to work on this until late next week. If it hasn't yet been resolved by then, I'll take a stab at it.


Resolving patch:
diff --git a/docker/client.py b/docker/client.py
--- a/docker/client.py
+++ b/docker/client.py
@@ -705,7 +705,7 @@ def search(self, term):
 
     def start(self, container, binds=None, port_bindings=None, lxc_conf=None,
               publish_all_ports=False, links=None, privileged=False,
-              dns=None, volumes_from=None, network_mode=None):
+              dns=None, dns_search=None, volumes_from=None, network_mode=None):
         if isinstance(container, dict):
             container = container.get('Id')
 
@@ -759,6 +759,9 @@ def start(self, container, binds=None, port_bindings=None, lxc_conf=None,
                 warnings.warn(warning_message.format('volumes_from'),
                               DeprecationWarning)
 
+        if dns_search:
+            start_config['DnsSearch'] = dns_search
+
         if network_mode:
             start_config['NetworkMode'] = network_mode
 


Test patch:
Repository: docker/docker-py

Issue:
attach_socket returns a closed socket when TLS is enabled
https://github.com/d11wtq/dockerpty/issues/13 is actually a docker-py bug: a docker-py client communicating over TLS will always return a closed socket from `attach_socket()`. This appears to be because the response object (returned by `self.post`) is [garbage-collected at the end of the method](https://github.com/docker/docker-py/blob/master/docker/client.py#L379-L380), which presumably causes the connection to be closed:

``` python
        return self._get_raw_response_socket(self.post(
            u, None, params=self._attach_params(params), stream=True))
```

This is speculation, but maybe the TLS socket object (an instance of `ssl.SSLSocket`) doesn't keep a back-reference to whatever's managing the connection, so the response object is the only thing holding on to it. All I know is, I can make it work in a test script if I replicate `attach_socket()`'s behaviour but hold on to the response by assigning it to a local variable:

``` python
# `client` is a docker.Client with TLS enabled

container = client.create_container(image='busybox', command=['echo', 'hello', 'world']).get('Id')
params = {'stdout': 1, 'stderr': 1, 'logs': 1, 'stream': 1}

# this breaks
# socket = client.attach_socket(container, params)

# this works
url = client._url("/containers/{0}/attach".format(container))
response = client.post(url, None, params=client._attach_params(params), stream=True)
socket = client._get_raw_response_socket(response)

client.start(container)

while True:
    chunk = socket.recv(4096)
    if chunk == '':
        break
    print 'got chunk:', repr(chunk)
```

I'm thinking about possible fixes. It might be necessary to return an object which wraps the `SSLSocket` and keeps a reference to the response - annoying/icky to be adding another layer of wrapping, though.

In any case, this is a complete blocker for any program hoping to attach over TLS - such as Fig.



Discussion:

Resolving patch:
diff --git a/docker/client.py b/docker/client.py
--- a/docker/client.py
+++ b/docker/client.py
@@ -259,9 +259,11 @@ def _create_websocket_connection(self, url):
     def _get_raw_response_socket(self, response):
         self._raise_for_status(response)
         if six.PY3:
-            return response.raw._fp.fp.raw._sock
+            sock = response.raw._fp.fp.raw._sock
         else:
-            return response.raw._fp.fp._sock
+            sock = response.raw._fp.fp._sock
+        sock._response = response
+        return sock
 
     def _stream_helper(self, response):
         """Generator for data coming from a chunked-encoded HTTP response."""


Test patch:
Repository: docker/docker-py

Issue:
Streaming broken on Python3
See Issue #336!

Fix lost data & hangs when reading chunked streams
I managed to [track down a hang when calling `build()`](https://groups.google.com/forum/#!topic/docker-dev/fhrTqwF7IJQ) to a problem handling streams.

`strace` proved that the problem was somewhere in the python client and I manage to create a test harness for this issue.

This is not the most elegant fix, I could do with some advice:
- I've changed the return value of attach_socket
- In _stream_helper it creates a new fileobj, when we just threw away the one which had our data buffer in it, we could just keep the old one.



Discussion:

It looks like these codepaths are untested and broken on python 3, even without my changes.

As an aisde: the reason why this test harness does not hang is that we close the connection after sending the response

@leth are you going to try to fix those broken paths? I can make a stab at it, but I didn't want to duplicate any work you'd already done.

@micahhausler Go for it! I was hoping for some input from the core devs because the cleanest solutions would probably involve API changes. I'm a bit busy at the moment as well, so not likely to get anywhere with it.


Resolving patch:
diff --git a/docker/client.py b/docker/client.py
--- a/docker/client.py
+++ b/docker/client.py
@@ -277,7 +277,12 @@ def _get_raw_response_socket(self, response):
 
     def _stream_helper(self, response):
         """Generator for data coming from a chunked-encoded HTTP response."""
-        socket_fp = socket_obj(_sock=self._get_raw_response_socket(response))
+        if six.PY3:
+            socket_fp = self._get_raw_response_socket(response)
+        else:
+            socket_fp = socket_obj(
+                _sock=self._get_raw_response_socket(response)
+            )
         socket_fp.setblocking(1)
         socket = socket_fp.makefile()
         while True:


Test patch:
Repository: docker/docker-py

Issue:
Do not support sslv3 (poodle)
In Docker 1.3.1 (coming very soon), only TLS1.0+ will be supported.
Ping @shin- 



Discussion:

Resolving patch:
diff --git a/docker/ssladapter/ssladapter.py b/docker/ssladapter/ssladapter.py
--- a/docker/ssladapter/ssladapter.py
+++ b/docker/ssladapter/ssladapter.py
@@ -4,6 +4,7 @@
 """
 from distutils.version import StrictVersion
 from requests.adapters import HTTPAdapter
+import ssl
 try:
     import requests.packages.urllib3 as urllib3
 except ImportError:
@@ -13,9 +14,19 @@
 PoolManager = urllib3.poolmanager.PoolManager
 
 
+def get_max_tls_protocol():
+    protocols = ('PROTOCOL_TLSv1_2',
+                 'PROTOCOL_TLSv1_1',
+                 'PROTOCOL_TLSv1')
+    for proto in protocols:
+        if hasattr(ssl, proto):
+            return proto
+
+
 class SSLAdapter(HTTPAdapter):
     '''An HTTPS Transport Adapter that uses an arbitrary SSL version.'''
     def __init__(self, ssl_version=None, assert_hostname=None, **kwargs):
+        ssl_version = ssl_version or get_max_tls_protocol()
         self.ssl_version = ssl_version
         self.assert_hostname = assert_hostname
         super(SSLAdapter, self).__init__(**kwargs)
diff --git a/docker/tls.py b/docker/tls.py
--- a/docker/tls.py
+++ b/docker/tls.py
@@ -17,8 +17,11 @@ def __init__(self, client_cert=None, ca_cert=None, verify=None,
         # here, but also disable any public/default CA pool verification by
         # leaving tls_verify=False
 
-        # urllib3 sets a default ssl_version if ssl_version is None
-        # http://tinyurl.com/kxga8hb
+        # urllib3 sets a default ssl_version if ssl_version is None,
+        # but that default is the vulnerable PROTOCOL_SSLv23 selection,
+        # so we override the default with the maximum supported in the running
+        # Python interpeter up to TLS 1.2. (see: http://tinyurl.com/kxga8hb)
+        ssl_version = ssl_version or ssladapter.get_max_tls_protocol()
         self.ssl_version = ssl_version
         self.assert_hostname = assert_hostname
 


Test patch:
Repository: docker/docker-py

Issue:
Ensure client version is a string.
I was bitten by specifying the Docker client version as a float rather than a string.

Example test case:

``` python
>>> import docker
>>> client = docker.Client(version=1.14)
>>> client.containers()
[]
>>> client.pull('ubuntu')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "docker/client.py", line 816, in pull
    if utils.compare_version('1.5', self._version) >= 0:
  File "docker/utils/utils.py", line 100, in compare_version
    s2 = StrictVersion(v2)
  File "/usr/lib/python2.7/distutils/version.py", line 40, in __init__
    self.parse(vstring)
  File "/usr/lib/python2.7/distutils/version.py", line 105, in parse
    match = self.version_re.match(vstring)
TypeError: expected string or buffer

>>> client = docker.Client(version='1.14')
>>> client.containers()
[]
>>> client.pull('ubuntu')
u'{"status":"Pulling repository ubuntu"} [... snip ...] "id":"0b310e6bf058"}'
```



Discussion:
I'd rather take a more restrictive route and raise an exception if a non-string is passed, what do you think?

I agree with @shin-. If for some reason Python's `str()` returns something strange (like `"1.14000000001"`) then you'll hit the wrong endpoint without you knowing (other than via a 404).


Resolving patch:
diff --git a/docker/client.py b/docker/client.py
--- a/docker/client.py
+++ b/docker/client.py
@@ -50,6 +50,12 @@ def __init__(self, base_url=None, version=DEFAULT_DOCKER_API_VERSION,
             raise errors.TLSParameterError(
                 'If using TLS, the base_url argument must begin with '
                 '"https://".')
+        if not isinstance(version, six.string_types):
+            raise errors.DockerException(
+                'version parameter must be a string. Found {0}'.format(
+                    type(version).__name__
+                )
+            )
         self.base_url = base_url
         self._version = version
         self._timeout = timeout


Test patch:
diff --git a/tests/test.py b/tests/test.py
--- a/tests/test.py
+++ b/tests/test.py
@@ -102,6 +102,17 @@ def setUp(self):
     def tearDown(self):
         self.client.close()
 
+    def test_ctor(self):
+        try:
+            docker.Client(version=1.12)
+        except Exception as e:
+            self.assertTrue(isinstance(e, docker.errors.DockerException))
+            if not six.PY3:
+                self.assertEqual(
+                    e.message,
+                    'version parameter must be a string. Found float'
+                )
+
     #########################
     #   INFORMATION TESTS   #
     #########################
Repository: docker/docker-py

Issue:
Add support for dockerfile param to build
Docker 1.5 added a new param `dockerfile` to the `/build` endpoint. http://docs.docker.com/reference/api/docker_remote_api_v1.17/#build-image-from-a-dockerfile

I don't see a PR or issue for this already, apologies if I missed it.



Discussion:

Resolving patch:
diff --git a/docker/client.py b/docker/client.py
--- a/docker/client.py
+++ b/docker/client.py
@@ -275,7 +275,7 @@ def attach_socket(self, container, params=None, ws=False):
     def build(self, path=None, tag=None, quiet=False, fileobj=None,
               nocache=False, rm=False, stream=False, timeout=None,
               custom_context=False, encoding=None, pull=True,
-              forcerm=False):
+              forcerm=False, dockerfile=None):
         remote = context = headers = None
         if path is None and fileobj is None:
             raise TypeError("Either path or fileobj needs to be provided.")
@@ -302,6 +302,11 @@ def build(self, path=None, tag=None, quiet=False, fileobj=None,
         if utils.compare_version('1.8', self._version) >= 0:
             stream = True
 
+        if dockerfile and utils.compare_version('1.17', self._version) < 0:
+            raise errors.InvalidVersion(
+                'dockerfile was only introduced in API version 1.17'
+            )
+
         u = self._url('/build')
         params = {
             't': tag,
@@ -310,7 +315,8 @@ def build(self, path=None, tag=None, quiet=False, fileobj=None,
             'nocache': nocache,
             'rm': rm,
             'forcerm': forcerm,
-            'pull': pull
+            'pull': pull,
+            'dockerfile': dockerfile
         }
 
         if context is not None:


Test patch:
diff --git a/tests/test.py b/tests/test.py
--- a/tests/test.py
+++ b/tests/test.py
@@ -2095,6 +2095,12 @@ def test_build_remote_with_registry_auth(self):
         except Exception as e:
             self.fail('Command should not raise exception: {0}'.format(e))
 
+    def test_build_container_with_named_dockerfile(self):
+        try:
+            self.client.build('.', dockerfile='nameddockerfile')
+        except Exception as e:
+            self.fail('Command should not raise exception: {0}'.format(e))
+
     #######################
     #  PY SPECIFIC TESTS  #
     #######################
Repository: docker/docker-py

Issue:
.dockerignore and Dockerfile ignore
Docker 1.5 introduced the ability to ignore both the .dockerignore and the Dockerfile (in the .dockerignore file), but this is processed on the server since and only for dealing with the build cache (ie, when someone does ADD., Dockerfile changes can be ignored).

If Dockerfile is in .dockerignore, Dockerfile won't be sent to the server, so the server can't build it

Basically, .dockerignore, and Dockerfile should be treated as special case entries in the .dockerignore so that they still get sent up to the server.



Discussion:

Resolving patch:
diff --git a/docker/client.py b/docker/client.py
--- a/docker/client.py
+++ b/docker/client.py
@@ -297,6 +297,12 @@ def build(self, path=None, tag=None, quiet=False, fileobj=None,
             if os.path.exists(dockerignore):
                 with open(dockerignore, 'r') as f:
                     exclude = list(filter(bool, f.read().split('\n')))
+                    # These are handled by the docker daemon and should not be
+                    # excluded on the client
+                    if 'Dockerfile' in exclude:
+                        exclude.remove('Dockerfile')
+                    if '.dockerignore' in exclude:
+                        exclude.remove(".dockerignore")
             context = utils.tar(path, exclude=exclude)
 
         if utils.compare_version('1.8', self._version) >= 0:


Test patch:
diff --git a/tests/integration_test.py b/tests/integration_test.py
--- a/tests/integration_test.py
+++ b/tests/integration_test.py
@@ -1311,6 +1311,8 @@ def runTest(self):
         with open(os.path.join(base_dir, '.dockerignore'), 'w') as f:
             f.write("\n".join([
                 'node_modules',
+                'Dockerfile',
+                '.dockerginore',
                 '',  # empty line
             ]))
 
@@ -1329,6 +1331,8 @@ def runTest(self):
                 chunk = chunk.decode('utf-8')
             logs += chunk
         self.assertFalse('node_modules' in logs)
+        self.assertFalse('Dockerfile' in logs)
+        self.assertFalse('.dockerginore' in logs)
         self.assertTrue('not-ignored' in logs)
 
 #######################
Repository: docker/docker-py

Issue:
`Client.port` fails when called on a container with `network_mode=host`
This happens because the response JSON has `None` for ports rather than an empty dictionary, which results in calling `None.get(portname)`, which barfs.



Discussion:

Resolving patch:
diff --git a/docker/client.py b/docker/client.py
--- a/docker/client.py
+++ b/docker/client.py
@@ -702,9 +702,15 @@ def port(self, container, private_port):
         s_port = str(private_port)
         h_ports = None
 
-        h_ports = json_['NetworkSettings']['Ports'].get(s_port + '/udp')
+        # Port settings is None when the container is running with
+        # network_mode=host.
+        port_settings = json_['NetworkSettings']['Ports']
+        if port_settings is None:
+            return None
+
+        h_ports = port_settings.get(s_port + '/udp')
         if h_ports is None:
-            h_ports = json_['NetworkSettings']['Ports'].get(s_port + '/tcp')
+            h_ports = port_settings.get(s_port + '/tcp')
 
         return h_ports
 


Test patch:
Repository: docker/docker-py

Issue:
Add support for Docker v2 registries
I'm here via Saltstack, and troubleshooting a issue with connectivity while doing a pull. The problem is that the library is hardcoded to reference the v1 API to verify SSL connectivity to a local registry, which does not work with v2 registry.

The request should be changed to also try and ping `https:// + hostname + "/v2/"` in addition to `'https://' + hostname + '/v1/_ping'`

The rest of the pull stream works OK, since it is connecting to Docker, not the repo directly otherwise.

See: https://github.com/docker/docker-py/blob/master/docker/auth/auth.py#L32



Discussion:

Resolving patch:
diff --git a/docker/auth/auth.py b/docker/auth/auth.py
--- a/docker/auth/auth.py
+++ b/docker/auth/auth.py
@@ -29,7 +29,7 @@
 def expand_registry_url(hostname, insecure=False):
     if hostname.startswith('http:') or hostname.startswith('https:'):
         return hostname
-    if utils.ping('https://' + hostname + '/v1/_ping'):
+    if utils.ping_registry('https://' + hostname):
         return 'https://' + hostname
     elif insecure:
         return 'http://' + hostname
diff --git a/docker/utils/__init__.py b/docker/utils/__init__.py
--- a/docker/utils/__init__.py
+++ b/docker/utils/__init__.py
@@ -1,6 +1,6 @@
 from .utils import (
     compare_version, convert_port_bindings, convert_volume_binds,
-    mkbuildcontext, ping, tar, parse_repository_tag, parse_host,
+    mkbuildcontext, tar, parse_repository_tag, parse_host,
     kwargs_from_env, convert_filters, create_host_config,
-    create_container_config, parse_bytes
+    create_container_config, parse_bytes, ping_registry
 ) # flake8: noqa
diff --git a/docker/utils/utils.py b/docker/utils/utils.py
--- a/docker/utils/utils.py
+++ b/docker/utils/utils.py
@@ -118,6 +118,10 @@ def compare_version(v1, v2):
         return 1
 
 
+def ping_registry(url):
+    return ping(url + '/v2/_ping') or ping(url + '/v1/_ping')
+
+
 def ping(url):
     try:
         res = requests.get(url, timeout=3)


Test patch:
Repository: docker/docker-py

Issue:
docker.utils.decorators.check_resource problem
When use `docker_client.start(**kwargs)` to start the container, will be raise follow exception:

```
c.start(**s_kwargs)
  File "/home/simplecloud/shiyanlou/env/local/lib/python2.7/site-packages/docker/utils/decorators.py", line 12, in wrapped
    return f(self, resource_id, *args, **kwargs)
TypeError: start() got multiple values for keyword argument 'container'
```



Discussion:

Resolving patch:
diff --git a/docker/utils/decorators.py b/docker/utils/decorators.py
--- a/docker/utils/decorators.py
+++ b/docker/utils/decorators.py
@@ -3,11 +3,14 @@
 
 def check_resource(f):
     def wrapped(self, resource_id=None, *args, **kwargs):
-        if resource_id is None and (
-            kwargs.get('container') is None and kwargs.get('image') is None
-        ):
-            raise errors.NullResource(
-                'image or container param is None'
-            )
+        if resource_id is None:
+            if kwargs.get('container'):
+                resource_id = kwargs.pop('container')
+            elif kwargs.get('image'):
+                resource_id = kwargs.pop('image')
+            else:
+                raise errors.NullResource(
+                    'image or container param is undefined'
+                )
         return f(self, resource_id, *args, **kwargs)
     return wrapped
diff --git a/docker/version.py b/docker/version.py
--- a/docker/version.py
+++ b/docker/version.py
@@ -1,2 +1,2 @@
-version = "1.2.1-dev"
+version = "1.2.1"
 version_info = tuple([int(d) for d in version.replace("-dev", "").split(".")])


Test patch:
diff --git a/tests/test.py b/tests/test.py
--- a/tests/test.py
+++ b/tests/test.py
@@ -675,17 +675,23 @@ def test_start_container_none(self):
         try:
             self.client.start(container=None)
         except ValueError as e:
-            self.assertEqual(str(e), 'image or container param is None')
+            self.assertEqual(str(e), 'image or container param is undefined')
         else:
             self.fail('Command should raise ValueError')
 
         try:
             self.client.start(None)
         except ValueError as e:
-            self.assertEqual(str(e), 'image or container param is None')
+            self.assertEqual(str(e), 'image or container param is undefined')
         else:
             self.fail('Command should raise ValueError')
 
+    def test_start_container_regression_573(self):
+        try:
+            self.client.start(**{'container': fake_api.FAKE_CONTAINER_ID})
+        except Exception as e:
+            self.fail('Command should not raise exception: {0}'.format(e))
+
     def test_create_container_with_lxc_conf(self):
         try:
             self.client.create_container(