From 23798250c339acf9448c51f6bc18dcf9ec6856b2 Mon Sep 17 00:00:00 2001 From: Brandon W Maister Date: Fri, 19 Aug 2016 18:37:28 -0400 Subject: [PATCH 1/2] Syntactic changes to support python3 --- eureka/ec2metadata.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/eureka/ec2metadata.py b/eureka/ec2metadata.py index 9d4f807..4e5dea3 100644 --- a/eureka/ec2metadata.py +++ b/eureka/ec2metadata.py @@ -1,3 +1,4 @@ +from __future__ import print_function # Copyright (c) 2013 Alon Swartz # # This file is part of ec2metadata. @@ -39,7 +40,7 @@ def _test_connectivity(addr, port): s.connect((addr, port)) s.close() return True - except socket.error, e: + except socket.error as e: time.sleep(1) return False @@ -95,6 +96,6 @@ def display(metaopts, prefix=False): value = "unavailable" if prefix: - print "%s: %s" % (metaopt, value) + print("%s: %s" % (metaopt, value)) else: - print value + print(value) From e938cf18ed5f0b1f487a78100f6cb286f2221de2 Mon Sep 17 00:00:00 2001 From: Brandon W Maister Date: Fri, 19 Aug 2016 18:37:36 -0400 Subject: [PATCH 2/2] Support python3 via python-future Added some incredibly bare-bones tests just to make sure that imports work, my code that depends on this all works in 2 and 3. --- MANIFEST.in | 1 + eureka/client.py | 10 +++++++--- eureka/ec2metadata.py | 18 +++++++++++++----- eureka/requests.py | 22 ++++++++++++++-------- requirements.testing.txt | 2 ++ requirements.txt | 2 ++ setup.cfg | 2 ++ setup.py | 32 +++++++++++++++++++++----------- tests/test_client.py | 8 ++++++++ tests/test_ec2metadata.py | 5 +++++ tests/test_requests.py | 5 +++++ tox.ini | 11 +++++++++++ 12 files changed, 91 insertions(+), 27 deletions(-) create mode 100644 MANIFEST.in create mode 100644 requirements.testing.txt create mode 100644 requirements.txt create mode 100644 setup.cfg create mode 100644 tests/test_client.py create mode 100644 tests/test_ec2metadata.py create mode 100644 tests/test_requests.py create mode 100644 tox.ini diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..607da8f --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1 @@ +include requirements* diff --git a/eureka/client.py b/eureka/client.py index 2cc0d6f..1b6d24e 100644 --- a/eureka/client.py +++ b/eureka/client.py @@ -1,7 +1,11 @@ +from future import standard_library +standard_library.install_aliases() +from builtins import str +from builtins import object import json import random -from urllib2 import URLError -from urlparse import urljoin +from urllib.error import URLError +from urllib.parse import urljoin from eureka import requests from eureka import ec2metadata import logging @@ -86,7 +90,7 @@ def get_eureka_urls(self): return [self.eureka_url] elif self.use_dns: zone_dns_map = self.get_zones_from_dns() - zones = zone_dns_map.keys() + zones = list(zone_dns_map.keys()) assert len(zones) > 0, "No availability zones found for, please add them explicitly" if self.prefer_same_zone: if self.get_instance_zone() in zones: diff --git a/eureka/ec2metadata.py b/eureka/ec2metadata.py index 4e5dea3..33834e2 100644 --- a/eureka/ec2metadata.py +++ b/eureka/ec2metadata.py @@ -1,4 +1,8 @@ from __future__ import print_function +from future import standard_library +standard_library.install_aliases() +from builtins import range +from builtins import object # Copyright (c) 2013 Alon Swartz # # This file is part of ec2metadata. @@ -9,7 +13,7 @@ # option) any later version. # import time -import urllib +from urllib import request import socket METAOPTS = ['ami-id', 'ami-launch-index', 'ami-manifest-path', @@ -19,10 +23,12 @@ 'public-keys', 'ramdisk-id', 'reservation-id', 'security-groups', 'user-data'] + class Error(Exception): pass -class EC2Metadata: + +class EC2Metadata(object): """Class for querying metadata from EC2""" def __init__(self, addr='169.254.169.254', api='2008-02-01'): @@ -40,14 +46,14 @@ def _test_connectivity(addr, port): s.connect((addr, port)) s.close() return True - except socket.error as e: + except socket.error: time.sleep(1) return False def _get(self, uri): url = 'http://%s/%s/%s' % (self.addr, self.api, uri) - value = urllib.urlopen(url).read() + value = request.urlopen(url).read() if "404 - Not Found" in value: return None @@ -68,7 +74,7 @@ def get(self, metaopt): if not data: return public_keys - keyids = [ line.split('=')[0] for line in data.splitlines() ] + keyids = [line.split('=')[0] for line in data.splitlines()] for keyid in keyids: uri = 'meta-data/public-keys/%d/openssh-key' % int(keyid) public_keys.append(self._get(uri).rstrip()) @@ -80,12 +86,14 @@ def get(self, metaopt): return self._get('meta-data/' + metaopt) + def get(metaopt): """primitive: return value of metaopt""" m = EC2Metadata() return m.get(metaopt) + def display(metaopts, prefix=False): """primitive: display metaopts (list) values with optional prefix""" diff --git a/eureka/requests.py b/eureka/requests.py index dbd7e73..83aaa96 100644 --- a/eureka/requests.py +++ b/eureka/requests.py @@ -1,4 +1,7 @@ -import urllib2 +from future import standard_library +standard_library.install_aliases() +from builtins import object +from urllib import request, error from eureka import __version__ as client_version @@ -6,19 +9,22 @@ class EurekaHTTPException(Exception): pass -class Request(urllib2.Request): +class Request(request.Request): """ - Instead of requiring a version of `requests`, we use this easy wrapper around urllib2 to avoud possible - version conflicts with people own software. + Utility wrapper around urllib.Request + + Instead of requiring a version of `requests`, we use this easy wrapper + around urllib2 to avoud possible version conflicts with people own + software. """ def __init__(self, url, method="GET", data=None, headers=None, origin_req_host=None, unverifiable=False): self.method = method - self._opener = urllib2.build_opener() + self._opener = request.build_opener() self._opener.addheaders = [ ('User-agent', 'python-eureka v%s' % client_version) ] - urllib2.Request.__init__(self, url, data=data, headers=headers or {}, + request.Request.__init__(self, url, data=data, headers=headers or {}, origin_req_host=origin_req_host, unverifiable=unverifiable) def get_method(self): @@ -30,7 +36,7 @@ def create(cls, method, url, data=None, headers=None): request = cls(url, method, data=data, headers=headers) try: response = request._opener.open(request) - except urllib2.HTTPError as e: + except error.HTTPError as e: return Response(e.code, e.read(), url, method) return Response(response.getcode(), response.read(), url, method) @@ -63,4 +69,4 @@ def put(url, data=None, headers=None): def delete(url, data=None, headers=None): - return Request.create("DELETE", url, data, headers) \ No newline at end of file + return Request.create("DELETE", url, data, headers) diff --git a/requirements.testing.txt b/requirements.testing.txt new file mode 100644 index 0000000..26b77f6 --- /dev/null +++ b/requirements.testing.txt @@ -0,0 +1,2 @@ +-r requirements.txt +pytest diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..f0a567f --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +dnspython +future diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..2a9acf1 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,2 @@ +[bdist_wheel] +universal = 1 diff --git a/setup.py b/setup.py index 5cb6da5..337d3c1 100644 --- a/setup.py +++ b/setup.py @@ -2,16 +2,26 @@ from setuptools import setup, find_packages from eureka import __version__ as version +import os + + +def here(fname): + return os.path.join(os.path.dirname(__file__), fname) + setup( - name = 'python-eureka', - version = version, - description = 'A python interface for Netflix Eureka', - author = u'Kristian Øllegaard', - author_email = 'kristian@oellegaard.com', + name='python-eureka', + version=version, + description='A python interface for Netflix Eureka', + author=u'Kristian Øllegaard', + author_email='kristian@oellegaard.com', zip_safe=False, - include_package_data = True, - packages = find_packages(exclude=[]), - install_requires=[ - 'dnspython' - ], -) \ No newline at end of file + include_package_data=True, + packages=find_packages(exclude=[]), + install_requires=open(here('requirements.txt')).readlines(), + classifiers=[ + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.5', + ] +) diff --git a/tests/test_client.py b/tests/test_client.py new file mode 100644 index 0000000..d703133 --- /dev/null +++ b/tests/test_client.py @@ -0,0 +1,8 @@ +"""Simple validation that anything works +""" + +from eureka import client + + +def test_client_exists(): + client.EurekaClient diff --git a/tests/test_ec2metadata.py b/tests/test_ec2metadata.py new file mode 100644 index 0000000..a110e87 --- /dev/null +++ b/tests/test_ec2metadata.py @@ -0,0 +1,5 @@ +from eureka import ec2metadata + + +def test_ec2metadata_dummy(): + ec2metadata.EC2Metadata diff --git a/tests/test_requests.py b/tests/test_requests.py new file mode 100644 index 0000000..93ff8bb --- /dev/null +++ b/tests/test_requests.py @@ -0,0 +1,5 @@ +from eureka import requests + + +def test_requests_dummy(): + requests.Request diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..df088f1 --- /dev/null +++ b/tox.ini @@ -0,0 +1,11 @@ +[tox] +envlist = py27, py35 + + +[pytest] +testpaths = tests + +[testenv] +deps = + -rrequirements.testing.txt +commands = py.test