Skip to content

Commit d2a94d3

Browse files
committed
feat(*): use latest python (3.5 right now) for API
from __future__ import unicode_literals is not needed anymore, see http://python-future.org/unicode_literals.html xrange is now range in python 3 and exception needs as instead of comma as a separator print needs parentheses basestring is replaced with str
1 parent f29b72e commit d2a94d3

41 files changed

Lines changed: 109 additions & 148 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ before_install:
2424
- wget "http://ftp.debian.org/debian/pool/main/s/shellcheck/shellcheck_0.3.7-5_amd64.deb"
2525
- sudo dpkg -i shellcheck_0.3.7-5_amd64.deb
2626
- sudo pip install virtualenv
27-
- virtualenv $HOME/venv
27+
- virtualenv -p python3.5 $HOME/venv
2828
- source $HOME/venv/bin/activate
2929
- createdb -U postgres deis
3030
install:

rootfs/api/admin.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
Django admin app configuration for Deis API models.
55
"""
66

7-
from __future__ import unicode_literals
87

98
from django.contrib import admin
109
from guardian.admin import GuardedModelAdmin

rootfs/api/fields.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
Deis API custom fields for representing data in Django forms.
33
"""
44

5-
from __future__ import unicode_literals
65
from django.db import models
76

87

rootfs/api/management/commands/load_db_state_to_etcd.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ class Command(BaseCommand):
99
"""
1010
def handle(self, *args, **options):
1111
"""Publishes Deis platform state from the database to etcd."""
12-
print "Publishing DB state to etcd..."
12+
print("Publishing DB state to etcd...")
1313
for model in (Key, App, Domain, Certificate, Config):
1414
for obj in model.objects.all():
1515
obj.save()
16-
print "Done Publishing DB state to etcd."
16+
print("Done Publishing DB state to etcd.")

rootfs/api/migrations/0001_initial.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
# -*- coding: utf-8 -*-
2-
from __future__ import unicode_literals
32

43
from django.db import models, migrations
54
import jsonfield.fields

rootfs/api/migrations/0002_auto_20151215_0352.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
# -*- coding: utf-8 -*-
2-
from __future__ import unicode_literals
32

43
from django.db import migrations, models
54
import api.models

rootfs/api/models.py

Lines changed: 20 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
Data models for the Deis API.
55
"""
66

7-
from __future__ import unicode_literals
87
import base64
98
from datetime import datetime
109
import etcd
@@ -18,19 +17,16 @@
1817
from django.conf import settings
1918
from django.core.exceptions import ValidationError, SuspiciousOperation
2019
from django.db import models
21-
from django.db.models import Count
22-
from django.db.models import Max
20+
from django.db.models import Count, Max
2321
from django.db.models.signals import post_delete, post_save
2422
from django.dispatch import receiver
25-
from django.utils.encoding import python_2_unicode_compatible
2623
from jsonfield import JSONField
2724
from OpenSSL import crypto
2825
import requests
2926
from rest_framework.authtoken.models import Token
3027

31-
from api import utils
3228
from registry import publish_release
33-
from utils import dict_diff, dict_merge, fingerprint
29+
from api.utils import dict_diff, dict_merge, fingerprint, generate_app_name
3430

3531

3632
User = settings.AUTH_USER_MODEL
@@ -82,9 +78,9 @@ def validate_id_is_docker_compatible(value):
8278
def validate_app_structure(value):
8379
"""Error if the dict values aren't ints >= 0."""
8480
try:
85-
if any(int(v) < 0 for v in value.viewvalues()):
81+
if any(int(v) < 0 for v in value.values()):
8682
raise ValueError("Must be greater than or equal to zero")
87-
except ValueError, err:
83+
except ValueError as err:
8884
raise ValidationError(err)
8985

9086

@@ -141,7 +137,6 @@ class Meta:
141137
abstract = True
142138

143139

144-
@python_2_unicode_compatible
145140
class App(UuidAuditedModel):
146141
"""
147142
Application used to service requests on behalf of end-users
@@ -159,9 +154,9 @@ class Meta:
159154
@property
160155
def select_app_name(self):
161156
"""Select a unique randomly generated app name"""
162-
name = utils.generate_app_name()
157+
name = generate_app_name()
163158
while App.objects.filter(id=name).exists():
164-
name = utils.generate_app_name()
159+
name = generate_app_name()
165160

166161
return name
167162

@@ -174,9 +169,9 @@ def _scheduler(self):
174169

175170
def save(self, **kwargs):
176171
if not self.id:
177-
self.id = utils.generate_app_name()
172+
self.id = generate_app_name()
178173
while App.objects.filter(id=self.id).exists():
179-
self.id = utils.generate_app_name()
174+
self.id = generate_app_name()
180175

181176
return super(App, self).save(**kwargs)
182177

@@ -265,15 +260,15 @@ def scale(self, user, structure): # noqa
265260
raise EnvironmentError(
266261
'Container type {} does not exist in application'.format(container_type))
267262
msg = '{} scaled containers '.format(user.username) + ' '.join(
268-
"{}={}".format(k, v) for k, v in requested_structure.items())
263+
"{}={}".format(k, v) for k, v in list(requested_structure.items()))
269264
log_event(self, msg)
270265
# iterate and scale by container type (web, worker, etc)
271266
changed = False
272267
to_add, to_remove = [], []
273268
scale_types = {}
274269

275270
# iterate on a copy of the container_type keys
276-
for container_type in requested_structure.keys():
271+
for container_type in list(requested_structure.keys()):
277272
containers = list(self.container_set.filter(type=container_type).order_by('created'))
278273
# increment new container nums off the most recent container
279274
results = self.container_set.filter(type=container_type).aggregate(Max('num'))
@@ -518,7 +513,6 @@ def run(self, user, command):
518513
return c.run(escaped_command)
519514

520515

521-
@python_2_unicode_compatible
522516
class Container(UuidAuditedModel):
523517
"""
524518
Docker container used to securely host an application process.
@@ -649,7 +643,6 @@ def run(self, command):
649643
raise
650644

651645

652-
@python_2_unicode_compatible
653646
class Push(UuidAuditedModel):
654647
"""
655648
Instance of a push used to trigger an application build
@@ -674,7 +667,6 @@ def __str__(self):
674667
return "{0}-{1}".format(self.app.id, self.sha[:7])
675668

676669

677-
@python_2_unicode_compatible
678670
class Build(UuidAuditedModel):
679671
"""
680672
Instance of a software build used by runtime nodes
@@ -728,7 +720,6 @@ def __str__(self):
728720
return "{0}-{1}".format(self.app.id, str(self.uuid)[:7])
729721

730722

731-
@python_2_unicode_compatible
732723
class Config(UuidAuditedModel):
733724
"""
734725
Set of configuration values applied as environment variables
@@ -778,15 +769,14 @@ def save(self, **kwargs):
778769

779770
data.update(new_data)
780771
# remove config keys if we provided a null value
781-
[data.pop(k) for k, v in new_data.viewitems() if v is None]
772+
[data.pop(k) for k, v in new_data.items() if v is None]
782773
setattr(self, attr, data)
783774
except Config.DoesNotExist:
784775
pass
785776

786777
return super(Config, self).save(**kwargs)
787778

788779

789-
@python_2_unicode_compatible
790780
class Release(UuidAuditedModel):
791781
"""
792782
Software release deployed by the application platform
@@ -953,7 +943,6 @@ def save(self, *args, **kwargs): # noqa
953943
super(Release, self).save(*args, **kwargs)
954944

955945

956-
@python_2_unicode_compatible
957946
class Domain(AuditedModel):
958947
owner = models.ForeignKey(settings.AUTH_USER_MODEL)
959948
app = models.ForeignKey('App')
@@ -997,7 +986,7 @@ def _save_service_config(self, app, component, data):
997986
component = "%s.deis.io/" % component
998987

999988
# add component to data and flatten
1000-
data = {"%s%s" % (component, key): value for key, value in data.items()}
989+
data = {"%s%s" % (component, key): value for key, value in list(data.items())}
1001990
svc['metadata']['annotations'].update(morph.flatten(data))
1002991

1003992
# Update the k8s service for the application with new domain information
@@ -1015,7 +1004,7 @@ def save(self, *args, **kwargs):
10151004
config['domains'] = ''
10161005

10171006
# convert from string to list to work with and filter out empty strings
1018-
domains = filter(None, config['domains'].split(','))
1007+
domains = [_f for _f in config['domains'].split(',') if _f]
10191008
if domain not in domains:
10201009
domains.append(domain)
10211010
config['domains'] = ','.join(domains)
@@ -1037,7 +1026,7 @@ def delete(self, *args, **kwargs):
10371026
config['domains'] = ''
10381027

10391028
# convert from string to list to work with and filter out empty strings
1040-
domains = filter(None, config['domains'].split(','))
1029+
domains = [_f for _f in config['domains'].split(',') if _f]
10411030
if domain in domains:
10421031
domains.remove(domain)
10431032
config['domains'] = ','.join(domains)
@@ -1051,7 +1040,6 @@ def __str__(self):
10511040
return self.domain
10521041

10531042

1054-
@python_2_unicode_compatible
10551043
class Certificate(AuditedModel):
10561044
"""
10571045
Public and private key pair used to secure application traffic at the router.
@@ -1077,13 +1065,17 @@ def save(self, *args, **kwargs):
10771065
certificate = self._get_certificate()
10781066
if not self.common_name:
10791067
self.common_name = certificate.get_subject().CN
1068+
10801069
if not self.expires:
1070+
# https://pyopenssl.readthedocs.org/en/latest/api/crypto.html#OpenSSL.crypto.X509.get_notAfter
1071+
# Convert bytes to string
1072+
timestamp = certificate.get_notAfter().decode(encoding='UTF-8')
10811073
# convert openssl's expiry date format to Django's DateTimeField format
1082-
self.expires = datetime.strptime(certificate.get_notAfter(), '%Y%m%d%H%M%SZ')
1074+
self.expires = datetime.strptime(timestamp, '%Y%m%d%H%M%SZ')
1075+
10831076
return super(Certificate, self).save(*args, **kwargs)
10841077

10851078

1086-
@python_2_unicode_compatible
10871079
class Key(UuidAuditedModel):
10881080
"""An SSH public key."""
10891081

rootfs/api/routers.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
REST framework URL routing classes.
33
"""
44

5-
from __future__ import unicode_literals
65

76
from rest_framework.routers import DefaultRouter
87
from rest_framework.routers import Route

rootfs/api/serializers.py

Lines changed: 26 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
Classes to serialize the RESTful representation of Deis API models.
33
"""
44

5-
from __future__ import unicode_literals
65
import json
76
import re
87

@@ -35,7 +34,7 @@ def to_internal_value(self, data):
3534

3635
def to_representation(self, obj):
3736
"""Serialize the field's JSON data, for read operations."""
38-
for k, v in obj.viewitems():
37+
for k, v in obj.items():
3938
if v is None: # NoneType is used to unset a value
4039
continue
4140

@@ -143,64 +142,64 @@ class Meta:
143142
"""Metadata options for a :class:`ConfigSerializer`."""
144143
model = models.Config
145144

146-
def validate_values(self, value):
147-
for k, v in value.viewitems():
148-
if not re.match(CONFIGKEY_MATCH, k):
145+
def validate_values(self, data):
146+
for key, value in data.items():
147+
if not re.match(CONFIGKEY_MATCH, key):
149148
raise serializers.ValidationError(
150149
"Config keys must start with a letter or underscore and "
151150
"only contain [A-z0-9_]")
152151

153-
return value
152+
return data
154153

155-
def validate_memory(self, value):
156-
for k, v in value.viewitems():
157-
if v is None: # use NoneType to unset a value
154+
def validate_memory(self, data):
155+
for key, value in data.items():
156+
if value is None: # use NoneType to unset an item
158157
continue
159158

160-
if not re.match(PROCTYPE_MATCH, k):
159+
if not re.match(PROCTYPE_MATCH, key):
161160
raise serializers.ValidationError("Process types can only contain [a-z]")
162161

163-
if not re.match(MEMLIMIT_MATCH, str(v)):
162+
if not re.match(MEMLIMIT_MATCH, str(value)):
164163
raise serializers.ValidationError(
165164
"Limit format: <number><unit>, where unit = B, K, M or G")
166165

167-
return value
166+
return data
168167

169-
def validate_cpu(self, value):
170-
for k, v in value.viewitems():
171-
if v is None: # use NoneType to unset a value
168+
def validate_cpu(self, data):
169+
for key, value in data.items():
170+
if value is None: # use NoneType to unset an item
172171
continue
173172

174-
if not re.match(PROCTYPE_MATCH, k):
173+
if not re.match(PROCTYPE_MATCH, key):
175174
raise serializers.ValidationError("Process types can only contain [a-z]")
176175

177-
shares = re.match(CPUSHARE_MATCH, str(v))
176+
shares = re.match(CPUSHARE_MATCH, str(value))
178177
if not shares:
179178
raise serializers.ValidationError("CPU shares must be an integer")
180179

181-
for v in shares.groupdict().viewvalues():
180+
for share in shares.groupdict().values():
182181
try:
183-
i = int(v)
182+
i = int(share)
184183
except ValueError:
185184
raise serializers.ValidationError("CPU shares must be an integer")
186185

187186
if i > 1024 or i < 0:
188187
raise serializers.ValidationError("CPU shares must be between 0 and 1024")
189188

190-
return value
189+
return data
191190

192-
def validate_tags(self, value):
193-
for k, v in value.viewitems():
194-
if v is None: # use NoneType to unset a value
191+
def validate_tags(self, data):
192+
for key, value in data.items():
193+
if value is None: # use NoneType to unset an item
195194
continue
196195

197-
if not re.match(TAGKEY_MATCH, k):
196+
if not re.match(TAGKEY_MATCH, key):
198197
raise serializers.ValidationError("Tag keys can only contain [a-z]")
199198

200-
if not re.match(TAGVAL_MATCH, str(v)):
201-
raise serializers.ValidationError("Invalid tag value")
199+
if not re.match(TAGVAL_MATCH, str(value)):
200+
raise serializers.ValidationError("Invalid tag data")
202201

203-
return value
202+
return data
204203

205204

206205
class ReleaseSerializer(serializers.ModelSerializer):

rootfs/api/tests/__init__.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
from __future__ import unicode_literals
21
import logging
32

43
from django.test.runner import DiscoverRunner

0 commit comments

Comments
 (0)