Forráskód Böngészése

First version with python3 support.

 * Moved requirements*.txt files to proper spec definitions in setup.py
 * Added a new fig.compat module to store some compatibility code
Christopher Grebs 11 éve
szülő
commit
93b9b6fd9f

+ 3 - 1
MANIFEST.in

@@ -1,3 +1,5 @@
 include LICENSE
 include *.md
-include requirements.txt
+recursive-include tests *
+global-exclude *.pyc
+global-exclode *.pyo

+ 1 - 0
fig/__init__.py

@@ -1,3 +1,4 @@
+from __future__ import unicode_literals
 from .service import Service
 
 __version__ = '0.0.2'

+ 1 - 0
fig/cli/colors.py

@@ -1,3 +1,4 @@
+from __future__ import unicode_literals
 NAMES = [
     'grey',
     'red',

+ 3 - 1
fig/cli/command.py

@@ -1,3 +1,5 @@
+from __future__ import unicode_literals
+from __future__ import absolute_import
 from docker import Client
 import errno
 import logging
@@ -21,7 +23,7 @@ class Command(DocoptCommand):
     def project(self):
         try:
             config = yaml.load(open('fig.yml'))
-        except IOError, e:
+        except IOError as e:
             if e.errno == errno.ENOENT:
                 log.error("Can't find %s. Are you in the right directory?", e.filename)
             else:

+ 2 - 0
fig/cli/docopt_command.py

@@ -1,3 +1,5 @@
+from __future__ import unicode_literals
+from __future__ import absolute_import
 import sys
 
 from inspect import getdoc

+ 1 - 0
fig/cli/errors.py

@@ -1,3 +1,4 @@
+from __future__ import absolute_import
 from textwrap import dedent
 
 

+ 2 - 0
fig/cli/formatter.py

@@ -1,3 +1,5 @@
+from __future__ import unicode_literals
+from __future__ import absolute_import
 import texttable
 import os
 

+ 3 - 1
fig/cli/log_printer.py

@@ -1,3 +1,5 @@
+from __future__ import unicode_literals
+from __future__ import absolute_import
 import sys
 
 from itertools import cycle
@@ -41,7 +43,7 @@ class LogPrinter(object):
             'stream': True,
         }
         params.update(self.attach_params)
-        params = dict((name, 1 if value else 0) for (name, value) in params.items())
+        params = dict((name, 1 if value else 0) for (name, value) in list(params.items()))
         return container.attach_socket(params=params, ws=True)
 
 def read_websocket(websocket):

+ 1 - 0
fig/cli/multiplexer.py

@@ -1,3 +1,4 @@
+from __future__ import absolute_import
 from threading import Thread
 
 try:

+ 3 - 1
fig/cli/utils.py

@@ -1,3 +1,5 @@
+from __future__ import unicode_literals
+from __future__ import absolute_import
 import datetime
 import os
 import socket
@@ -69,7 +71,7 @@ def prettydate(d):
         return '{0} hours ago'.format(s/3600)
 
 
-def mkdir(path, permissions=0700):
+def mkdir(path, permissions=0o700):
     if not os.path.exists(path):
         os.mkdir(path)
 

+ 23 - 0
fig/compat.py

@@ -0,0 +1,23 @@
+
+
+# Taken from python2.7/3.3 functools
+def cmp_to_key(mycmp):
+    """Convert a cmp= function into a key= function"""
+    class K(object):
+        __slots__ = ['obj']
+        def __init__(self, obj):
+            self.obj = obj
+        def __lt__(self, other):
+            return mycmp(self.obj, other.obj) < 0
+        def __gt__(self, other):
+            return mycmp(self.obj, other.obj) > 0
+        def __eq__(self, other):
+            return mycmp(self.obj, other.obj) == 0
+        def __le__(self, other):
+            return mycmp(self.obj, other.obj) <= 0
+        def __ge__(self, other):
+            return mycmp(self.obj, other.obj) >= 0
+        def __ne__(self, other):
+            return mycmp(self.obj, other.obj) != 0
+        __hash__ = None
+    return K

+ 3 - 1
fig/container.py

@@ -1,3 +1,5 @@
+from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 
 log = logging.getLogger(__name__)
@@ -53,7 +55,7 @@ class Container(object):
         if not self.dictionary['NetworkSettings']['Ports']:
             return ''
         ports = []
-        for private, public in self.dictionary['NetworkSettings']['Ports'].items():
+        for private, public in list(self.dictionary['NetworkSettings']['Ports'].items()):
             if public:
                 ports.append('%s->%s' % (public[0]['HostPort'], private))
         return ', '.join(ports)

+ 5 - 2
fig/project.py

@@ -1,5 +1,8 @@
+from __future__ import unicode_literals
+from __future__ import absolute_import
 import logging
 from .service import Service
+from .compat import cmp_to_key
 
 log = logging.getLogger(__name__)
 
@@ -13,7 +16,7 @@ def sort_service_dicts(services):
         elif y_deps_x and not x_deps_y:
             return -1
         return 0
-    return sorted(services, cmp=cmp)
+    return sorted(services, key=cmp_to_key(cmp))
 
 class Project(object):
     """
@@ -43,7 +46,7 @@ class Project(object):
     @classmethod
     def from_config(cls, name, config, client):
         dicts = []
-        for service_name, service in config.items():
+        for service_name, service in list(config.items()):
             service['name'] = service_name
             dicts.append(service)
         return cls.from_dicts(name, dicts, client)

+ 6 - 4
fig/service.py

@@ -1,3 +1,5 @@
+from __future__ import unicode_literals
+from __future__ import absolute_import
 from docker.client import APIError
 import logging
 import re
@@ -64,7 +66,7 @@ class Service(object):
         container_options = self._get_container_options(override_options, one_off=one_off)
         try:
             return Container.create(self.client, **container_options)
-        except APIError, e:
+        except APIError as e:
             if e.response.status_code == 404 and e.explanation and 'No such image' in e.explanation:
                 log.info('Pulling image %s...' % container_options['image'])
                 self.client.pull(container_options['image'])
@@ -82,7 +84,7 @@ class Service(object):
 
         if options.get('ports', None) is not None:
             for port in options['ports']:
-                port = unicode(port)
+                port = str(port)
                 if ':' in port:
                     internal_port, external_port = port.split(':', 1)
                     port_bindings[int(internal_port)] = int(external_port)
@@ -107,7 +109,7 @@ class Service(object):
         bits = [self.project, self.name]
         if one_off:
             bits.append('run')
-        return '_'.join(bits + [unicode(self.next_container_number(one_off=one_off))])
+        return '_'.join(bits + [str(self.next_container_number(one_off=one_off))])
 
     def next_container_number(self, one_off=False):
         numbers = [parse_name(c.name)[2] for c in self.containers(stopped=True, one_off=one_off)]
@@ -132,7 +134,7 @@ class Service(object):
         container_options['name'] = self.next_container_name(one_off)
 
         if 'ports' in container_options:
-            container_options['ports'] = [unicode(p).split(':')[0] for p in container_options['ports']]
+            container_options['ports'] = [str(p).split(':')[0] for p in container_options['ports']]
 
         if 'volumes' in container_options:
             container_options['volumes'] = dict((v.split(':')[1], {}) for v in container_options['volumes'])

+ 0 - 2
requirements-dev.txt

@@ -1,2 +0,0 @@
-nose==1.3.0
-unittest2==0.5.1

+ 0 - 4
requirements.txt

@@ -1,4 +0,0 @@
-docker-py==0.2.3
-docopt==0.6.1
-PyYAML==3.10
-texttable==0.8.1

+ 20 - 10
setup.py

@@ -1,16 +1,17 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
-
-from setuptools import setup
+from __future__ import unicode_literals
+from __future__ import absolute_import
+from setuptools import setup, find_packages
 import re
 import os
 import codecs
 
 
-# Borrowed from
-# https://github.com/jezdez/django_compressor/blob/develop/setup.py
 def read(*parts):
-    return codecs.open(os.path.join(os.path.dirname(__file__), *parts)).read()
+    path = os.path.join(os.path.dirname(__file__), *parts)
+    with codecs.open(path, encoding='utf-8') as fobj:
+        return fobj.read()
 
 
 def find_version(*file_paths):
@@ -21,8 +22,6 @@ def find_version(*file_paths):
         return version_match.group(1)
     raise RuntimeError("Unable to find version string.")
 
-with open('requirements.txt') as f:
-    install_requires = f.read().splitlines()
 
 setup(
     name='fig',
@@ -31,10 +30,21 @@ setup(
     url='https://github.com/orchardup/fig',
     author='Orchard Laboratories Ltd.',
     author_email='[email protected]',
-    packages=['fig', 'fig.cli'],
-    package_data={},
+    packages=find_packages(),
     include_package_data=True,
-    install_requires=install_requires,
+    test_suite='nose.collector',
+    install_requires=[
+        'docker-py==0.2.3',
+        'docopt==0.6.1',
+        'PyYAML==3.10',
+        'texttable==0.8.1',
+        # unfortunately `docker` requires six ==1.3.0
+        'six==1.3.0',
+    ],
+    tests_require=[
+        'nose==1.3.0',
+        'unittest2==0.5.1'
+    ],
     entry_points="""
     [console_scripts]
     fig=fig.cli.main:main

+ 1 - 0
tests/container_test.py

@@ -1,3 +1,4 @@
+from __future__ import unicode_literals
 from .testcases import DockerClientTestCase
 from fig.container import Container
 

+ 1 - 0
tests/project_test.py

@@ -1,3 +1,4 @@
+from __future__ import unicode_literals
 from fig.project import Project
 from .testcases import DockerClientTestCase
 

+ 2 - 0
tests/service_test.py

@@ -1,3 +1,5 @@
+from __future__ import unicode_literals
+from __future__ import absolute_import
 from fig import Service
 from .testcases import DockerClientTestCase
 

+ 2 - 0
tests/testcases.py

@@ -1,3 +1,5 @@
+from __future__ import unicode_literals
+from __future__ import absolute_import
 from docker import Client
 from fig.service import Service
 from fig.cli.utils import docker_url