summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustin ! <just1602@riseup.net>2020-10-04 00:59:41 -0400
committerjelle van der Waa <jelle@vdwaa.nl>2020-11-11 22:23:29 +0100
commitc6cf91a40df69341dca8cec5e5971ff21cca0e04 (patch)
tree4f3a9de22010a5fd6e10a2d38801635b6d4f8b00
parent34de88278fc4bbcc72f83be4b40df881735f8a35 (diff)
downloadarchweb-c6cf91a40df69341dca8cec5e5971ff21cca0e04.tar.gz
archweb-c6cf91a40df69341dca8cec5e5971ff21cca0e04.zip
Fix pep8 errors
-rw-r--r--.flake81
-rw-r--r--devel/fields.py4
-rw-r--r--devel/forms.py32
-rw-r--r--devel/management/commands/generate_keyring.py7
-rw-r--r--devel/management/commands/pgp_import.py17
-rw-r--r--devel/management/commands/read_reproducible_status.py6
-rw-r--r--devel/management/commands/rematch_developers.py21
-rw-r--r--devel/management/commands/reporead.py79
-rw-r--r--devel/management/commands/reporead_inotify.py4
-rw-r--r--devel/management/commands/retire_user.py7
-rw-r--r--devel/migrations/0001_squashed_0002_staffgroup.py492
-rw-r--r--devel/migrations/0002_auto_20181216_1605.py443
-rw-r--r--devel/migrations/0003_auto_20191009_1924.py444
-rw-r--r--devel/migrations/0005_auto_20200628_1600.py4
-rw-r--r--devel/models.py54
-rw-r--r--devel/reports.py10
-rw-r--r--devel/templatetags/group.py1
-rw-r--r--devel/tests/test_devel.py4
-rw-r--r--devel/tests/test_pgp_import.py8
-rw-r--r--devel/tests/test_reporead.py17
-rw-r--r--devel/tests/test_reports.py4
-rw-r--r--devel/tests/test_retire_user.py5
-rw-r--r--devel/tests/test_user.py94
-rw-r--r--devel/utils.py14
-rw-r--r--devel/views.py5
-rw-r--r--feeds.py16
-rw-r--r--local_settings.py.example60
-rw-r--r--main/admin.py6
-rw-r--r--main/log.py2
-rw-r--r--main/management/commands/donor_import.py28
-rw-r--r--main/migrations/0001_initial.py29
-rw-r--r--main/migrations/0002_repo_public_testing.py3
-rw-r--r--main/models.py141
-rw-r--r--main/templatetags/attributes.py4
-rw-r--r--main/templatetags/cdn.py1
-rw-r--r--main/templatetags/flags.py2
-rw-r--r--main/templatetags/pgp.py6
-rw-r--r--main/tests/test_donor_import.py3
-rw-r--r--main/tests/test_templatetags_pgp.py1
-rw-r--r--main/utils.py3
-rw-r--r--mirrors/admin.py16
-rw-r--r--mirrors/management/commands/mirrorcheck.py14
-rw-r--r--mirrors/management/commands/mirrorresolv.py4
-rw-r--r--mirrors/migrations/0001_squashed_0002_mirrorurl_bandwidth.py32
-rw-r--r--mirrors/models.py26
-rw-r--r--mirrors/templatetags/mirror_status.py2
-rw-r--r--mirrors/tests/__init__.py16
-rw-r--r--mirrors/tests/test_mirrorcheck.py2
-rw-r--r--mirrors/tests/test_mirrorrsync.py1
-rw-r--r--mirrors/tests/test_templatetags.py2
-rw-r--r--mirrors/utils.py42
-rw-r--r--mirrors/views/__init__.py34
-rw-r--r--mirrors/views/api.py15
-rw-r--r--mirrors/views/mirrorlist.py44
-rw-r--r--news/migrations/0001_squashed_0002_news_send_announce.py3
-rw-r--r--news/models.py11
-rw-r--r--news/tests.py4
-rw-r--r--news/urls.py2
-rw-r--r--news/views.py14
-rw-r--r--packages/admin.py12
-rw-r--r--packages/alpm.py7
-rw-r--r--packages/management/commands/populate_signoffs.py18
-rw-r--r--packages/migrations/0001_squashed_0003_auto_20170524_0704.py55
-rw-r--r--packages/models.py109
-rw-r--r--packages/templatetags/package_extras.py6
-rw-r--r--packages/tests.py12
-rw-r--r--packages/urls.py40
-rw-r--r--packages/urls_groups.py2
-rw-r--r--packages/utils.py55
-rw-r--r--packages/views/__init__.py44
-rw-r--r--packages/views/display.py29
-rw-r--r--packages/views/flag.py65
-rw-r--r--packages/views/search.py36
-rw-r--r--packages/views/signoff.py52
-rw-r--r--planet/admin.py3
-rw-r--r--planet/migrations/0001_initial.py3
-rw-r--r--planet/models.py2
-rw-r--r--planet/tests/test_command.py1
-rw-r--r--releng/admin.py3
-rw-r--r--releng/migrations/0001_squashed_0005_auto_20180616_0947.py23
-rw-r--r--releng/migrations/0003_release_pgp_key.py3
-rw-r--r--releng/views.py6
-rw-r--r--settings.py6
-rw-r--r--sitemaps.py45
-rw-r--r--todolists/migrations/0001_squashed_0002_remove_todolist_old_id.py12
-rw-r--r--todolists/models.py6
-rw-r--r--todolists/tests/test_models.py6
-rw-r--r--todolists/tests/test_views.py5
-rw-r--r--todolists/urls.py2
-rw-r--r--todolists/utils.py8
-rw-r--r--todolists/views.py54
-rw-r--r--urls.py24
-rw-r--r--visualize/views.py12
93 files changed, 2255 insertions, 877 deletions
diff --git a/.flake8 b/.flake8
index 6deafc26..8a79e886 100644
--- a/.flake8
+++ b/.flake8
@@ -1,2 +1,3 @@
[flake8]
max-line-length = 120
+ignore = E731, E241, W503, E741
diff --git a/devel/fields.py b/devel/fields.py
index dd22a92e..a74abb97 100644
--- a/devel/fields.py
+++ b/devel/fields.py
@@ -5,8 +5,8 @@ from django.core.validators import RegexValidator
class PGPKeyField(models.CharField):
def __init__(self, *args, **kwargs):
super(PGPKeyField, self).__init__(*args, **kwargs)
- self.validators.append(RegexValidator(r'^[0-9A-F]{40}$',
- "Ensure this value consists of 40 hex characters.", 'hex_char'))
+ self.validators.append(
+ RegexValidator(r'^[0-9A-F]{40}$', "Ensure this value consists of 40 hex characters.", 'hex_char'))
def to_python(self, value):
if value == '' or value is None:
diff --git a/devel/forms.py b/devel/forms.py
index e6ccf68b..a3d589e0 100644
--- a/devel/forms.py
+++ b/devel/forms.py
@@ -12,12 +12,13 @@ from .models import UserProfile
class ProfileForm(forms.Form):
- email = forms.EmailField(label='Private email (not shown publicly):',
- help_text="Used for out-of-date notifications, etc.")
- passwd1 = forms.CharField(label='New Password', required=False,
- widget=forms.PasswordInput)
- passwd2 = forms.CharField(label='Confirm Password', required=False,
- widget=forms.PasswordInput)
+ email = forms.EmailField(
+ label='Private email (not shown publicly):',
+ help_text="Used for out-of-date notifications, etc.")
+ passwd1 = forms.CharField(
+ label='New Password', required=False, widget=forms.PasswordInput)
+ passwd2 = forms.CharField(
+ label='Confirm Password', required=False, widget=forms.PasswordInput)
def clean(self):
if self.cleaned_data['passwd1'] != self.cleaned_data['passwd2']:
@@ -43,8 +44,7 @@ class NewUserForm(forms.ModelForm):
private_email = forms.EmailField()
first_name = forms.CharField(required=False)
last_name = forms.CharField(required=False)
- groups = forms.ModelMultipleChoiceField(required=False,
- queryset=Group.objects.all())
+ groups = forms.ModelMultipleChoiceField(required=False, queryset=Group.objects.all())
class Meta:
model = UserProfile
@@ -66,16 +66,16 @@ class NewUserForm(forms.ModelForm):
def clean_username(self):
username = self.cleaned_data['username']
if User.objects.filter(username=username).exists():
- raise forms.ValidationError(
- "A user with that username already exists.")
+ raise forms.ValidationError("A user with that username already exists.")
return username
def save(self, commit=True):
profile = super(NewUserForm, self).save(False)
pwletters = ascii_letters + digits
password = ''.join([random.choice(pwletters) for _ in range(8)])
- user = User.objects.create_user(username=self.cleaned_data['username'],
- email=self.cleaned_data['private_email'], password=password)
+ user = User.objects.create_user(
+ username=self.cleaned_data['username'],
+ email=self.cleaned_data['private_email'], password=password)
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.save()
@@ -95,9 +95,9 @@ class NewUserForm(forms.ModelForm):
}
send_mail("Your new archweb account",
- template.render(ctx),
- 'Arch Website Notification <nobody@archlinux.org>',
- [user.email],
- fail_silently=False)
+ template.render(ctx),
+ 'Arch Website Notification <nobody@archlinux.org>',
+ [user.email],
+ fail_silently=False)
# vim: set ts=4 sw=4 et:
diff --git a/devel/management/commands/generate_keyring.py b/devel/management/commands/generate_keyring.py
index a61cffa9..3e6a3e9f 100644
--- a/devel/management/commands/generate_keyring.py
+++ b/devel/management/commands/generate_keyring.py
@@ -22,6 +22,7 @@ logging.basicConfig(
stream=sys.stderr)
logger = logging.getLogger()
+
class Command(BaseCommand):
args = "<keyserver> <keyring_path> [ownertrust_path]"
help = "Assemble a GPG keyring with all known developer keys."
@@ -52,8 +53,8 @@ def generate_keyring(keyserver, keyring):
# Screw you Django, for not letting one natively do value != <empty string>
key_ids = UserProfile.objects.filter(
- pgp_key__isnull=False).extra(where=["pgp_key != ''"]).values_list(
- "pgp_key", flat=True)
+ pgp_key__isnull=False).extra(where=["pgp_key != ''"]).values_list(
+ "pgp_key", flat=True)
logger.info("%d keys fetched from user profiles", len(key_ids))
master_key_ids = MasterKey.objects.values_list("pgp_key", flat=True)
logger.info("%d keys fetched from master keys", len(master_key_ids))
@@ -63,7 +64,7 @@ def generate_keyring(keyserver, keyring):
if '/' not in keyring:
keyring = './%s' % keyring
gpg_cmd = ["gpg", "--no-default-keyring", "--keyring", keyring,
- "--keyserver", keyserver, "--recv-keys"]
+ "--keyserver", keyserver, "--recv-keys"]
logger.info("running command: %r", gpg_cmd)
gpg_cmd.extend(key_ids)
gpg_cmd.extend(master_key_ids)
diff --git a/devel/management/commands/pgp_import.py b/devel/management/commands/pgp_import.py
index a0b9cbec..00ff5a49 100644
--- a/devel/management/commands/pgp_import.py
+++ b/devel/management/commands/pgp_import.py
@@ -28,6 +28,7 @@ logging.basicConfig(
stream=sys.stderr)
logger = logging.getLogger()
+
class Command(BaseCommand):
args = "<keyring_path>"
help = "Import keys and signatures from a given GPG keyring."
@@ -71,7 +72,7 @@ def call_gpg(keyring, *args):
if '/' not in keyring:
keyring = './%s' % keyring
gpg_cmd = ["gpg2", "--no-default-keyring", "--keyring", keyring,
- "--with-colons", "--fixed-list-mode"]
+ "--with-colons", "--fixed-list-mode"]
gpg_cmd.extend(args)
logger.info("running command: %s", ' '.join(gpg_cmd))
proc = subprocess.Popen(gpg_cmd, stdout=subprocess.PIPE)
@@ -153,7 +154,7 @@ def import_keys(keyring):
'parent_id': parent_id,
}
dkey, created = DeveloperKey.objects.get_or_create(
- key=data.key, created=data.created, defaults=other)
+ key=data.key, created=data.created, defaults=other)
data.db_id = dkey.id
# set or update any additional data we might need to
@@ -216,8 +217,7 @@ def parse_sigdata(data):
signer = parts[4]
revoked = get_date(parts[5])
# revoke any prior edges that match
- matches = [e for e in edges if e.signer == signer
- and e.signee == current_pubkey]
+ matches = [e for e in edges if e.signer == signer and e.signee == current_pubkey]
for edge in matches:
edge.revoked = revoked
@@ -230,17 +230,16 @@ def import_signatures(keyring):
# now prune the data down to what we actually want.
# prune edges not in nodes, remove duplicates, and self-sigs
- pruned_edges = {edge for edge in edges
- if edge.signer in nodes and edge.signer != edge.signee}
+ pruned_edges = {edge for edge in edges if edge.signer in nodes and edge.signer != edge.signee}
logger.info("creating or finding up to %d signatures", len(pruned_edges))
created_ct = updated_ct = 0
with transaction.atomic():
for edge in pruned_edges:
sig, created = PGPSignature.objects.get_or_create(
- signer=edge.signer, signee=edge.signee,
- created=edge.created, expires=edge.expires,
- defaults={ 'revoked': edge.revoked })
+ signer=edge.signer, signee=edge.signee,
+ created=edge.created, expires=edge.expires,
+ defaults={'revoked': edge.revoked})
if sig.revoked != edge.revoked:
sig.revoked = edge.revoked
sig.save()
diff --git a/devel/management/commands/read_reproducible_status.py b/devel/management/commands/read_reproducible_status.py
index ba317753..8db8b6cd 100644
--- a/devel/management/commands/read_reproducible_status.py
+++ b/devel/management/commands/read_reproducible_status.py
@@ -119,7 +119,8 @@ def import_rebuilderd_status(url):
rbstatus.was_repro = False
if rbstatus.pkgver != pkgver or rbstatus.pkgrel != pkgrel or rbstatus.epoch != epoch:
- logger.info('updating status for package: %s to %s', pkg['name'], RebuilderdStatus.REBUILDERD_STATUSES[status][1])
+ logger.info('updating status for package: %s to %s', pkg['name'],
+ RebuilderdStatus.REBUILDERD_STATUSES[status][1])
rbstatus.epoch = epoch
rbstatus.pkgver = pkgver
rbstatus.pkgrel = pkgrel
@@ -127,7 +128,8 @@ def import_rebuilderd_status(url):
rbstatus.arch = arch
rbstatus.repo = repository
elif rbstatus.status != status: # Rebuilderd rebuild the same package?
- logger.info('status for package: %s changed to %s', pkg['name'], RebuilderdStatus.REBUILDERD_STATUSES[status][1])
+ logger.info('status for package: %s changed to %s', pkg['name'],
+ RebuilderdStatus.REBUILDERD_STATUSES[status][1])
rbstatus.status = status
# TODO: does django know when a model was really modified?
diff --git a/devel/management/commands/rematch_developers.py b/devel/management/commands/rematch_developers.py
index 7178d1d8..f6cc95c8 100644
--- a/devel/management/commands/rematch_developers.py
+++ b/devel/management/commands/rematch_developers.py
@@ -28,6 +28,7 @@ logging.basicConfig(
stream=sys.stderr)
logger = logging.getLogger()
+
class Command(BaseCommand):
help = "Match and map objects in database to developer emails"
@@ -44,6 +45,7 @@ class Command(BaseCommand):
match_packager(finder)
match_flagrequest(finder)
+
@transaction.atomic
def match_packager(finder):
logger.info("getting all unmatched packager strings")
@@ -51,7 +53,7 @@ def match_packager(finder):
mapping = {}
unmatched = Package.objects.filter(packager__isnull=True).values_list(
- 'packager_str', flat=True).order_by().distinct()
+ 'packager_str', flat=True).order_by().distinct()
logger.info("%d packager strings retrieved", len(unmatched))
for packager in unmatched:
@@ -63,11 +65,11 @@ def match_packager(finder):
matched_count += 1
for packager_str, user in mapping.items():
- package_count += Package.objects.filter(packager__isnull=True,
- packager_str=packager_str).update(packager=user)
+ package_count += Package.objects.filter(
+ packager__isnull=True,
+ packager_str=packager_str).update(packager=user)
- logger.info("%d packages updated, %d packager strings matched",
- package_count, matched_count)
+ logger.info("%d packages updated, %d packager strings matched", package_count, matched_count)
@transaction.atomic
@@ -77,7 +79,7 @@ def match_flagrequest(finder):
mapping = {}
unmatched = FlagRequest.objects.filter(user__isnull=True).values_list(
- 'user_email', flat=True).order_by().distinct()
+ 'user_email', flat=True).order_by().distinct()
logger.info("%d email addresses retrieved", len(unmatched))
for user_email in unmatched:
@@ -89,10 +91,9 @@ def match_flagrequest(finder):
matched_count += 1
for user_email, user in mapping.items():
- req_count += FlagRequest.objects.filter(user__isnull=True,
- user_email=user_email).update(user=user)
+ req_count += FlagRequest.objects.filter(
+ user__isnull=True, user_email=user_email).update(user=user)
- logger.info("%d request emails updated, %d emails matched",
- req_count, matched_count)
+ logger.info("%d request emails updated, %d emails matched", req_count, matched_count)
# vim: set ts=4 sw=4 et:
diff --git a/devel/management/commands/reporead.py b/devel/management/commands/reporead.py
index ba80ebe5..afb4d5d3 100644
--- a/devel/management/commands/reporead.py
+++ b/devel/management/commands/reporead.py
@@ -46,6 +46,7 @@ TRACE = 5
logging.addLevelName(TRACE, 'TRACE')
logger = logging.getLogger()
+
class Command(BaseCommand):
help = "Runs a package repository import for the given arch and file."
missing_args_message = 'missing arch and file.'
@@ -56,13 +57,17 @@ class Command(BaseCommand):
action='store_true',
dest='force',
default=False,
- help='Force a re-import of data for all packages instead of only new ones. Will not touch the \'last updated\' value.')
+ help='Force a re-import of data for all packages \
+ instead of only new ones. Will not touch \
+ the \'last updated\' value.')
parser.add_argument('--filesonly',
action='store_true',
dest='filesonly',
default=False,
- help='Load filelists if they are outdated, but will not add or remove any packages. Will not touch the \'last updated\' value.')
+ help='Load filelists if they are outdated, but will \
+ not add or remove any packages. Will not touch the \
+ \'last updated\' value.')
def handle(self, arch=None, filename=None, **options):
if not arch:
@@ -86,11 +91,11 @@ class Command(BaseCommand):
class RepoPackage(object):
"""An interim 'container' object for holding Arch package data."""
- bare = ( 'name', 'base', 'arch', 'filename',
- 'md5sum', 'sha256sum', 'url', 'packager' )
- number = ( 'csize', 'isize' )
- collections = ( 'depends', 'optdepends', 'makedepends', 'checkdepends',
- 'conflicts', 'provides', 'replaces', 'groups', 'license')
+ bare = ('name', 'base', 'arch', 'filename',
+ 'md5sum', 'sha256sum', 'url', 'packager')
+ number = ('csize', 'isize')
+ collections = ('depends', 'optdepends', 'makedepends', 'checkdepends',
+ 'conflicts', 'provides', 'replaces', 'groups', 'license')
def __init__(self, repo):
self.repo = repo
@@ -124,8 +129,8 @@ class RepoPackage(object):
self.builddate = builddate.replace(tzinfo=utc)
except ValueError:
logger.warning(
- 'Package %s had unparsable build date %s',
- self.name, v[0])
+ 'Package %s had unparsable build date %s',
+ self.name, v[0])
else:
# anything left in collections
setattr(self, k, tuple(v))
@@ -137,7 +142,7 @@ class RepoPackage(object):
info = parse_info(data_file)
except UnicodeDecodeError:
logger.warning("Could not correctly decode files list for %s",
- self.name)
+ self.name)
return None
return info['files']
@@ -151,6 +156,7 @@ class RepoPackage(object):
DEPEND_RE = re.compile(r"^(.+?)((>=|<=|=|>|<)(.+))?$")
+
def create_depend(package, dep_str, deptype='D'):
depend = Depend(pkg=package, deptype=deptype)
# lop off any description first, don't get confused by epoch
@@ -166,10 +172,11 @@ def create_depend(package, dep_str, deptype='D'):
depend.version = match.group(4)
else:
logger.warning('Package %s had unparsable depend string %s',
- package.pkgname, dep_str)
+ package.pkgname, dep_str)
return None
return depend
+
def create_related(model, package, rel_str, equals_only=False):
related = model(pkg=package)
match = DEPEND_RE.match(rel_str)
@@ -181,13 +188,13 @@ def create_related(model, package, rel_str, equals_only=False):
related.comparison = comp
elif comp != '=':
logger.warning(
- 'Package %s had unexpected comparison operator %s for %s in %s',
- package.pkgname, comp, model.__name__, rel_str)
+ 'Package %s had unexpected comparison operator %s for %s in %s',
+ package.pkgname, comp, model.__name__, rel_str)
if match.group(4):
related.version = match.group(4)
else:
logger.warning('Package %s had unparsable %s string %s',
- package.pkgname, model.___name__, rel_str)
+ package.pkgname, model.___name__, rel_str)
return None
return related
@@ -206,8 +213,10 @@ def create_multivalued(dbpkg, repopkg, db_attr, repo_attr):
if new_items:
model.objects.bulk_create(new_items)
+
finder = UserFinder()
+
def populate_pkg(dbpkg, repopkg, force=False, timestamp=None):
# we reset the flag date only if the upstream version components change;
# e.g. epoch or pkgver, but not pkgrel
@@ -259,8 +268,7 @@ def populate_pkg(dbpkg, repopkg, force=False, timestamp=None):
Conflict.objects.bulk_create(conflicts)
dbpkg.provides.all().delete()
- provides = [create_related(Provision, dbpkg, y, equals_only=True)
- for y in repopkg.provides]
+ provides = [create_related(Provision, dbpkg, y, equals_only=True) for y in repopkg.provides]
Provision.objects.bulk_create(provides)
dbpkg.replaces.all().delete()
@@ -272,7 +280,7 @@ def populate_pkg(dbpkg, repopkg, force=False, timestamp=None):
pkg_same_version = lambda pkg, dbpkg: pkg.ver == dbpkg.pkgver \
- and pkg.rel == dbpkg.pkgrel and pkg.epoch == dbpkg.epoch
+ and pkg.rel == dbpkg.pkgrel and pkg.epoch == dbpkg.epoch
def delete_pkg_files(dbpkg):
@@ -303,8 +311,8 @@ def populate_files(dbpkg, repopkg, force=False):
if not force:
if not pkg_same_version(repopkg, dbpkg):
logger.info("DB version (%s) didn't match repo version "
- "(%s) for package %s, skipping file list addition",
- dbpkg.full_version, repopkg.full_version, dbpkg.pkgname)
+ "(%s) for package %s, skipping file list addition",
+ dbpkg.full_version, repopkg.full_version, dbpkg.pkgname)
return
if not dbpkg.files_last_update or not dbpkg.last_update:
pass
@@ -319,7 +327,7 @@ def populate_files(dbpkg, repopkg, force=False):
return
delete_pkg_files(dbpkg)
logger.info("adding %d files for package %s",
- len(files), dbpkg.pkgname)
+ len(files), dbpkg.pkgname)
pkg_files = []
# sort in normal alpha-order that pacman uses, rather than makepkg's
# default breadth-first, directory-first ordering
@@ -332,9 +340,9 @@ def populate_files(dbpkg, repopkg, force=False):
if filename == '':
filename = None
pkgfile = PackageFile(pkg=dbpkg,
- is_directory=(filename is None),
- directory=dirname,
- filename=filename)
+ is_directory=(filename is None),
+ directory=dirname,
+ filename=filename)
pkg_files.append(pkgfile)
batched_bulk_create(PackageFile, pkg_files)
dbpkg.files_last_update = now()
@@ -348,13 +356,12 @@ def update_common(archname, reponame, pkgs, sanity_check=True):
with transaction.atomic():
# force the transaction dirty, even though we will only do reads
# https://github.com/django/django/blob/3c447b108ac70757001171f7a4791f493880bf5b/docs/releases/1.3.txt#L606
- #transaction.set_dirty()
+ # transaction.set_dirty()
repository = Repo.objects.get(name__iexact=reponame)
architecture = Arch.objects.get(name=archname)
# no-arg order_by() removes even the default ordering; we don't need it
- dbpkgs = Package.objects.filter(
- arch=architecture, repo=repository).order_by()
+ dbpkgs = Package.objects.filter(arch=architecture, repo=repository).order_by()
logger.info("%d packages in current web DB", len(dbpkgs))
logger.info("%d packages in new updating DB", len(pkgs))
@@ -368,7 +375,7 @@ def update_common(archname, reponame, pkgs, sanity_check=True):
# Fewer than 20 packages makes the percentage check unreliable, but it
# also means we expect the repo to fluctuate a lot.
msg = "Package database %s (%s) has %.1f%% the number of packages " \
- "the web database"
+ "the web database"
if not sanity_check:
pass
elif repository.testing or repository.public_testing or repository.staging:
@@ -383,6 +390,7 @@ def update_common(archname, reponame, pkgs, sanity_check=True):
return dbpkgs
+
def db_update(archname, reponame, pkgs, force=False):
"""
Parses a list of packages and updates the packages database accordingly.
@@ -407,7 +415,7 @@ def db_update(archname, reponame, pkgs, force=False):
logger.info("Adding package %s", pkg.name)
timestamp = now()
dbpkg = Package(pkgname=pkg.name, arch=architecture, repo=repository,
- created=timestamp)
+ created=timestamp)
try:
with transaction.atomic():
populate_pkg(dbpkg, pkg, timestamp=timestamp)
@@ -417,8 +425,7 @@ def db_update(archname, reponame, pkgs, force=False):
pkgname=pkg.name).exclude(id=dbpkg.id).exists():
if not User.objects.filter(
package_relations__pkgbase=dbpkg.pkgbase,
- package_relations__type=PackageRelation.MAINTAINER
- ).exists():
+ package_relations__type=PackageRelation.MAINTAINER).exists():
packager = finder.find(pkg.packager)
if packager:
prel = PackageRelation(pkgbase=dbpkg.pkgbase,
@@ -426,12 +433,11 @@ def db_update(archname, reponame, pkgs, force=False):
type=PackageRelation.MAINTAINER)
prel.save()
-
except IntegrityError:
if architecture.agnostic:
logger.warning("Could not add package %s; "
- "not fatal if another thread beat us to it.",
- pkg.name)
+ "not fatal if another thread beat us to it.",
+ pkg.name)
else:
logger.exception("Could not add package %s", pkg.name)
@@ -579,6 +585,7 @@ def parse_repo(repopath):
logger.info("Finished repo parsing, %d total packages", len(pkgs))
return (reponame, pkgs.values())
+
def locate_arch(arch):
"Check if arch is valid."
if isinstance(arch, Arch):
@@ -586,8 +593,7 @@ def locate_arch(arch):
try:
return Arch.objects.get(name=arch)
except Arch.DoesNotExist:
- raise CommandError(
- 'Specified architecture %s is not currently known.' % arch)
+ raise CommandError('Specified architecture %s is not currently known.' % arch)
def read_repo(primary_arch, repo_file, options):
@@ -612,8 +618,7 @@ def read_repo(primary_arch, repo_file, options):
packages_arches[package.arch].append(package)
else:
raise Exception(
- "Package %s in database %s had wrong architecture %s" % (
- package.name, repo_file, package.arch))
+ f"Package {package.name} in database {repo_file} had wrong architecture {package.arch}")
del packages
database = router.db_for_write(Package)
diff --git a/devel/management/commands/reporead_inotify.py b/devel/management/commands/reporead_inotify.py
index fadcb881..d3003f77 100644
--- a/devel/management/commands/reporead_inotify.py
+++ b/devel/management/commands/reporead_inotify.py
@@ -205,8 +205,8 @@ class EventHandler(pyinotify.ProcessEvent):
arch = self.arch_lookup.get(event.path, None)
if arch is None:
logger.warning(
- 'Could not determine arch for %s, skipping update',
- path)
+ 'Could not determine arch for %s, skipping update',
+ path)
return
database = Database(arch, path)
self.databases[path] = database
diff --git a/devel/management/commands/retire_user.py b/devel/management/commands/retire_user.py
index 0a7259f3..8f4c6017 100644
--- a/devel/management/commands/retire_user.py
+++ b/devel/management/commands/retire_user.py
@@ -25,9 +25,9 @@ logging.basicConfig(
logger = logging.getLogger()
MAPPING = {
- 'Developers': 'Retired Developers',
- 'Trusted Users': 'Retired Trusted Users',
- 'Support Staff': 'Retired Support Staff',
+ 'Developers': 'Retired Developers',
+ 'Trusted Users': 'Retired Trusted Users',
+ 'Support Staff': 'Retired Support Staff',
}
@@ -38,7 +38,6 @@ class Command(BaseCommand):
def add_arguments(self, parser):
parser.add_argument('user', type=str)
-
def handle(self, *args, **options):
v = int(options.get('verbosity', 0))
if v == 0:
diff --git a/devel/migrations/0001_squashed_0002_staffgroup.py b/devel/migrations/0001_squashed_0002_staffgroup.py
index 90e8e3a1..b4788118 100644
--- a/devel/migrations/0001_squashed_0002_staffgroup.py
+++ b/devel/migrations/0001_squashed_0002_staffgroup.py
@@ -28,19 +28,31 @@ class Migration(migrations.Migration):
('created', models.DateTimeField()),
('expires', models.DateTimeField(blank=True, null=True)),
('revoked', models.DateTimeField(blank=True, null=True)),
- ('owner', models.ForeignKey(help_text='The developer this key belongs to', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='all_keys', to=settings.AUTH_USER_MODEL)),
- ('parent', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='devel.DeveloperKey')),
+ ('owner', models.ForeignKey(
+ help_text='The developer this key belongs to',
+ null=True, on_delete=django.db.models.deletion.CASCADE,
+ related_name='all_keys', to=settings.AUTH_USER_MODEL)),
+ ('parent', models.ForeignKey(
+ null=True, on_delete=django.db.models.deletion.SET_NULL, to='devel.DeveloperKey')),
],
),
migrations.CreateModel(
name='MasterKey',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('pgp_key', devel.fields.PGPKeyField(help_text='consists of 40 hex digits; use `gpg --fingerprint`', max_length=40, verbose_name='PGP key fingerprint')),
+ ('pgp_key', devel.fields.PGPKeyField(
+ help_text='consists of 40 hex digits; use `gpg --fingerprint`',
+ max_length=40, verbose_name='PGP key fingerprint')),
('created', models.DateField()),
('revoked', models.DateField(blank=True, null=True)),
- ('owner', models.ForeignKey(help_text='The developer holding this master key', on_delete=django.db.models.deletion.CASCADE, related_name='masterkey_owner', to=settings.AUTH_USER_MODEL)),
- ('revoker', models.ForeignKey(help_text='The developer holding the revocation certificate', on_delete=django.db.models.deletion.CASCADE, related_name='masterkey_revoker', to=settings.AUTH_USER_MODEL)),
+ ('owner', models.ForeignKey(
+ help_text='The developer holding this master key',
+ on_delete=django.db.models.deletion.CASCADE,
+ related_name='masterkey_owner', to=settings.AUTH_USER_MODEL)),
+ ('revoker', models.ForeignKey(
+ help_text='The developer holding the revocation certificate',
+ on_delete=django.db.models.deletion.CASCADE,
+ related_name='masterkey_revoker', to=settings.AUTH_USER_MODEL)),
],
options={
'ordering': ('created',),
@@ -51,8 +63,10 @@ class Migration(migrations.Migration):
name='PGPSignature',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('signer', devel.fields.PGPKeyField(db_index=True, max_length=40, verbose_name='Signer key fingerprint')),
- ('signee', devel.fields.PGPKeyField(db_index=True, max_length=40, verbose_name='Signee key fingerprint')),
+ ('signer', devel.fields.PGPKeyField(
+ db_index=True, max_length=40, verbose_name='Signer key fingerprint')),
+ ('signee', devel.fields.PGPKeyField(
+ db_index=True, max_length=40, verbose_name='Signee key fingerprint')),
('created', models.DateField()),
('expires', models.DateField(blank=True, null=True)),
('revoked', models.DateField(blank=True, null=True)),
@@ -67,12 +81,459 @@ class Migration(migrations.Migration):
name='UserProfile',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('notify', models.BooleanField(default=True, help_text="When enabled, send user 'flag out-of-date' notifications", verbose_name='Send notifications')),
- ('time_zone', models.CharField(choices=[('Africa/Abidjan', 'Africa/Abidjan'), ('Africa/Accra', 'Africa/Accra'), ('Africa/Addis_Ababa', 'Africa/Addis_Ababa'), ('Africa/Algiers', 'Africa/Algiers'), ('Africa/Asmara', 'Africa/Asmara'), ('Africa/Bamako', 'Africa/Bamako'), ('Africa/Bangui', 'Africa/Bangui'), ('Africa/Banjul', 'Africa/Banjul'), ('Africa/Bissau', 'Africa/Bissau'), ('Africa/Blantyre', 'Africa/Blantyre'), ('Africa/Brazzaville', 'Africa/Brazzaville'), ('Africa/Bujumbura', 'Africa/Bujumbura'), ('Africa/Cairo', 'Africa/Cairo'), ('Africa/Casablanca', 'Africa/Casablanca'), ('Africa/Ceuta', 'Africa/Ceuta'), ('Africa/Conakry', 'Africa/Conakry'), ('Africa/Dakar', 'Africa/Dakar'), ('Africa/Dar_es_Salaam', 'Africa/Dar_es_Salaam'), ('Africa/Djibouti', 'Africa/Djibouti'), ('Africa/Douala', 'Africa/Douala'), ('Africa/El_Aaiun', 'Africa/El_Aaiun'), ('Africa/Freetown', 'Africa/Freetown'), ('Africa/Gaborone', 'Africa/Gaborone'), ('Africa/Harare', 'Africa/Harare'), ('Africa/Johannesburg', 'Africa/Johannesburg'), ('Africa/Juba', 'Africa/Juba'), ('Africa/Kampala', 'Africa/Kampala'), ('Africa/Khartoum', 'Africa/Khartoum'), ('Africa/Kigali', 'Africa/Kigali'), ('Africa/Kinshasa', 'Africa/Kinshasa'), ('Africa/Lagos', 'Africa/Lagos'), ('Africa/Libreville', 'Africa/Libreville'), ('Africa/Lome', 'Africa/Lome'), ('Africa/Luanda', 'Africa/Luanda'), ('Africa/Lubumbashi', 'Africa/Lubumbashi'), ('Africa/Lusaka', 'Africa/Lusaka'), ('Africa/Malabo', 'Africa/Malabo'), ('Africa/Maputo', 'Africa/Maputo'), ('Africa/Maseru', 'Africa/Maseru'), ('Africa/Mbabane', 'Africa/Mbabane'), ('Africa/Mogadishu', 'Africa/Mogadishu'), ('Africa/Monrovia', 'Africa/Monrovia'), ('Africa/Nairobi', 'Africa/Nairobi'), ('Africa/Ndjamena', 'Africa/Ndjamena'), ('Africa/Niamey', 'Africa/Niamey'), ('Africa/Nouakchott', 'Africa/Nouakchott'), ('Africa/Ouagadougou', 'Africa/Ouagadougou'), ('Africa/Porto-Novo', 'Africa/Porto-Novo'), ('Africa/Sao_Tome', 'Africa/Sao_Tome'), ('Africa/Tripoli', 'Africa/Tripoli'), ('Africa/Tunis', 'Africa/Tunis'), ('Africa/Windhoek', 'Africa/Windhoek'), ('America/Adak', 'America/Adak'), ('America/Anchorage', 'America/Anchorage'), ('America/Anguilla', 'America/Anguilla'), ('America/Antigua', 'America/Antigua'), ('America/Araguaina', 'America/Araguaina'), ('America/Argentina/Buenos_Aires', 'America/Argentina/Buenos_Aires'), ('America/Argentina/Catamarca', 'America/Argentina/Catamarca'), ('America/Argentina/Cordoba', 'America/Argentina/Cordoba'), ('America/Argentina/Jujuy', 'America/Argentina/Jujuy'), ('America/Argentina/La_Rioja', 'America/Argentina/La_Rioja'), ('America/Argentina/Mendoza', 'America/Argentina/Mendoza'), ('America/Argentina/Rio_Gallegos', 'America/Argentina/Rio_Gallegos'), ('America/Argentina/Salta', 'America/Argentina/Salta'), ('America/Argentina/San_Juan', 'America/Argentina/San_Juan'), ('America/Argentina/San_Luis', 'America/Argentina/San_Luis'), ('America/Argentina/Tucuman', 'America/Argentina/Tucuman'), ('America/Argentina/Ushuaia', 'America/Argentina/Ushuaia'), ('America/Aruba', 'America/Aruba'), ('America/Asuncion', 'America/Asuncion'), ('America/Atikokan', 'America/Atikokan'), ('America/Bahia', 'America/Bahia'), ('America/Bahia_Banderas', 'America/Bahia_Banderas'), ('America/Barbados', 'America/Barbados'), ('America/Belem', 'America/Belem'), ('America/Belize', 'America/Belize'), ('America/Blanc-Sablon', 'America/Blanc-Sablon'), ('America/Boa_Vista', 'America/Boa_Vista'), ('America/Bogota', 'America/Bogota'), ('America/Boise', 'America/Boise'), ('America/Cambridge_Bay', 'America/Cambridge_Bay'), ('America/Campo_Grande', 'America/Campo_Grande'), ('America/Cancun', 'America/Cancun'), ('America/Caracas', 'America/Caracas'), ('America/Cayenne', 'America/Cayenne'), ('America/Cayman', 'America/Cayman'), ('America/Chicago', 'America/Chicago'), ('America/Chihuahua', 'America/Chihuahua'), ('America/Costa_Rica', 'America/Costa_Rica'), ('America/Creston', 'America/Creston'), ('America/Cuiaba', 'America/Cuiaba'), ('America/Curacao', 'America/Curacao'), ('America/Danmarkshavn', 'America/Danmarkshavn'), ('America/Dawson', 'America/Dawson'), ('America/Dawson_Creek', 'America/Dawson_Creek'), ('America/Denver', 'America/Denver'), ('America/Detroit', 'America/Detroit'), ('America/Dominica', 'America/Dominica'), ('America/Edmonton', 'America/Edmonton'), ('America/Eirunepe', 'America/Eirunepe'), ('America/El_Salvador', 'America/El_Salvador'), ('America/Fort_Nelson', 'America/Fort_Nelson'), ('America/Fortaleza', 'America/Fortaleza'), ('America/Glace_Bay', 'America/Glace_Bay'), ('America/Godthab', 'America/Godthab'), ('America/Goose_Bay', 'America/Goose_Bay'), ('America/Grand_Turk', 'America/Grand_Turk'), ('America/Grenada', 'America/Grenada'), ('America/Guadeloupe', 'America/Guadeloupe'), ('America/Guatemala', 'America/Guatemala'), ('America/Guayaquil', 'America/Guayaquil'), ('America/Guyana', 'America/Guyana'), ('America/Halifax', 'America/Halifax'), ('America/Havana', 'America/Havana'), ('America/Hermosillo', 'America/Hermosillo'), ('America/Indiana/Indianapolis', 'America/Indiana/Indianapolis'), ('America/Indiana/Knox', 'America/Indiana/Knox'), ('America/Indiana/Marengo', 'America/Indiana/Marengo'), ('America/Indiana/Petersburg', 'America/Indiana/Petersburg'), ('America/Indiana/Tell_City', 'America/Indiana/Tell_City'), ('America/Indiana/Vevay', 'America/Indiana/Vevay'), ('America/Indiana/Vincennes', 'America/Indiana/Vincennes'), ('America/Indiana/Winamac', 'America/Indiana/Winamac'), ('America/Inuvik', 'America/Inuvik'), ('America/Iqaluit', 'America/Iqaluit'), ('America/Jamaica', 'America/Jamaica'), ('America/Juneau', 'America/Juneau'), ('America/Kentucky/Louisville', 'America/Kentucky/Louisville'), ('America/Kentucky/Monticello', 'America/Kentucky/Monticello'), ('America/Kralendijk', 'America/Kralendijk'), ('America/La_Paz', 'America/La_Paz'), ('America/Lima', 'America/Lima'), ('America/Los_Angeles', 'America/Los_Angeles'), ('America/Lower_Princes', 'America/Lower_Princes'), ('America/Maceio', 'America/Maceio'), ('America/Managua', 'America/Managua'), ('America/Manaus', 'America/Manaus'), ('America/Marigot', 'America/Marigot'), ('America/Martinique', 'America/Martinique'), ('America/Matamoros', 'America/Matamoros'), ('America/Mazatlan', 'America/Mazatlan'), ('America/Menominee', 'America/Menominee'), ('America/Merida', 'America/Merida'), ('America/Metlakatla', 'America/Metlakatla'), ('America/Mexico_City', 'America/Mexico_City'), ('America/Miquelon', 'America/Miquelon'), ('America/Moncton', 'America/Moncton'), ('America/Monterrey', 'America/Monterrey'), ('America/Montevideo', 'America/Montevideo'), ('America/Montserrat', 'America/Montserrat'), ('America/Nassau', 'America/Nassau'), ('America/New_York', 'America/New_York'), ('America/Nipigon', 'America/Nipigon'), ('America/Nome', 'America/Nome'), ('America/Noronha', 'America/Noronha'), ('America/North_Dakota/Beulah', 'America/North_Dakota/Beulah'), ('America/North_Dakota/Center', 'America/North_Dakota/Center'), ('America/North_Dakota/New_Salem', 'America/North_Dakota/New_Salem'), ('America/Ojinaga', 'America/Ojinaga'), ('America/Panama', 'America/Panama'), ('America/Pangnirtung', 'America/Pangnirtung'), ('America/Paramaribo', 'America/Paramaribo'), ('America/Phoenix', 'America/Phoenix'), ('America/Port-au-Prince', 'America/Port-au-Prince'), ('America/Port_of_Spain', 'America/Port_of_Spain'), ('America/Porto_Velho', 'America/Porto_Velho'), ('America/Puerto_Rico', 'America/Puerto_Rico'), ('America/Punta_Arenas', 'America/Punta_Arenas'), ('America/Rainy_River', 'America/Rainy_River'), ('America/Rankin_Inlet', 'America/Rankin_Inlet'), ('America/Recife', 'America/Recife'), ('America/Regina', 'America/Regina'), ('America/Resolute', 'America/Resolute'), ('America/Rio_Branco', 'America/Rio_Branco'), ('America/Santarem', 'America/Santarem'), ('America/Santiago', 'America/Santiago'), ('America/Santo_Domingo', 'America/Santo_Domingo'), ('America/Sao_Paulo', 'America/Sao_Paulo'), ('America/Scoresbysund', 'America/Scoresbysund'), ('America/Sitka', 'America/Sitka'), ('America/St_Barthelemy', 'America/St_Barthelemy'), ('America/St_Johns', 'America/St_Johns'), ('America/St_Kitts', 'America/St_Kitts'), ('America/St_Lucia', 'America/St_Lucia'), ('America/St_Thomas', 'America/St_Thomas'), ('America/St_Vincent', 'America/St_Vincent'), ('America/Swift_Current', 'America/Swift_Current'), ('America/Tegucigalpa', 'America/Tegucigalpa'), ('America/Thule', 'America/Thule'), ('America/Thunder_Bay', 'America/Thunder_Bay'), ('America/Tijuana', 'America/Tijuana'), ('America/Toronto', 'America/Toronto'), ('America/Tortola', 'America/Tortola'), ('America/Vancouver', 'America/Vancouver'), ('America/Whitehorse', 'America/Whitehorse'), ('America/Winnipeg', 'America/Winnipeg'), ('America/Yakutat', 'America/Yakutat'), ('America/Yellowknife', 'America/Yellowknife'), ('Antarctica/Casey', 'Antarctica/Casey'), ('Antarctica/Davis', 'Antarctica/Davis'), ('Antarctica/DumontDUrville', 'Antarctica/DumontDUrville'), ('Antarctica/Macquarie', 'Antarctica/Macquarie'), ('Antarctica/Mawson', 'Antarctica/Mawson'), ('Antarctica/McMurdo', 'Antarctica/McMurdo'), ('Antarctica/Palmer', 'Antarctica/Palmer'), ('Antarctica/Rothera', 'Antarctica/Rothera'), ('Antarctica/Syowa', 'Antarctica/Syowa'), ('Antarctica/Troll', 'Antarctica/Troll'), ('Antarctica/Vostok', 'Antarctica/Vostok'), ('Arctic/Longyearbyen', 'Arctic/Longyearbyen'), ('Asia/Aden', 'Asia/Aden'), ('Asia/Almaty', 'Asia/Almaty'), ('Asia/Amman', 'Asia/Amman'), ('Asia/Anadyr', 'Asia/Anadyr'), ('Asia/Aqtau', 'Asia/Aqtau'), ('Asia/Aqtobe', 'Asia/Aqtobe'), ('Asia/Ashgabat', 'Asia/Ashgabat'), ('Asia/Atyrau', 'Asia/Atyrau'), ('Asia/Baghdad', 'Asia/Baghdad'), ('Asia/Bahrain', 'Asia/Bahrain'), ('Asia/Baku', 'Asia/Baku'), ('Asia/Bangkok', 'Asia/Bangkok'), ('Asia/Barnaul', 'Asia/Barnaul'), ('Asia/Beirut', 'Asia/Beirut'), ('Asia/Bishkek', 'Asia/Bishkek'), ('Asia/Brunei', 'Asia/Brunei'), ('Asia/Chita', 'Asia/Chita'), ('Asia/Choibalsan', 'Asia/Choibalsan'), ('Asia/Colombo', 'Asia/Colombo'), ('Asia/Damascus', 'Asia/Damascus'), ('Asia/Dhaka', 'Asia/Dhaka'), ('Asia/Dili', 'Asia/Dili'), ('Asia/Dubai', 'Asia/Dubai'), ('Asia/Dushanbe', 'Asia/Dushanbe'), ('Asia/Famagusta', 'Asia/Famagusta'), ('Asia/Gaza', 'Asia/Gaza'), ('Asia/Hebron', 'Asia/Hebron'), ('Asia/Ho_Chi_Minh', 'Asia/Ho_Chi_Minh'), ('Asia/Hong_Kong', 'Asia/Hong_Kong'), ('Asia/Hovd', 'Asia/Hovd'), ('Asia/Irkutsk', 'Asia/Irkutsk'), ('Asia/Jakarta', 'Asia/Jakarta'), ('Asia/Jayapura', 'Asia/Jayapura'), ('Asia/Jerusalem', 'Asia/Jerusalem'), ('Asia/Kabul', 'Asia/Kabul'), ('Asia/Kamchatka', 'Asia/Kamchatka'), ('Asia/Karachi', 'Asia/Karachi'), ('Asia/Kathmandu', 'Asia/Kathmandu'), ('Asia/Khandyga', 'Asia/Khandyga'), ('Asia/Kolkata', 'Asia/Kolkata'), ('Asia/Krasnoyarsk', 'Asia/Krasnoyarsk'), ('Asia/Kuala_Lumpur', 'Asia/Kuala_Lumpur'), ('Asia/Kuching', 'Asia/Kuching'), ('Asia/Kuwait', 'Asia/Kuwait'), ('Asia/Macau', 'Asia/Macau'), ('Asia/Magadan', 'Asia/Magadan'), ('Asia/Makassar', 'Asia/Makassar'), ('Asia/Manila', 'Asia/Manila'), ('Asia/Muscat', 'Asia/Muscat'), ('Asia/Nicosia', 'Asia/Nicosia'), ('Asia/Novokuznetsk', 'Asia/Novokuznetsk'), ('Asia/Novosibirsk', 'Asia/Novosibirsk'), ('Asia/Omsk', 'Asia/Omsk'), ('Asia/Oral', 'Asia/Oral'), ('Asia/Phnom_Penh', 'Asia/Phnom_Penh'), ('Asia/Pontianak', 'Asia/Pontianak'), ('Asia/Pyongyang', 'Asia/Pyongyang'), ('Asia/Qatar', 'Asia/Qatar'), ('Asia/Qyzylorda', 'Asia/Qyzylorda'), ('Asia/Riyadh', 'Asia/Riyadh'), ('Asia/Sakhalin', 'Asia/Sakhalin'), ('Asia/Samarkand', 'Asia/Samarkand'), ('Asia/Seoul', 'Asia/Seoul'), ('Asia/Shanghai', 'Asia/Shanghai'), ('Asia/Singapore', 'Asia/Singapore'), ('Asia/Srednekolymsk', 'Asia/Srednekolymsk'), ('Asia/Taipei', 'Asia/Taipei'), ('Asia/Tashkent', 'Asia/Tashkent'), ('Asia/Tbilisi', 'Asia/Tbilisi'), ('Asia/Tehran', 'Asia/Tehran'), ('Asia/Thimphu', 'Asia/Thimphu'), ('Asia/Tokyo', 'Asia/Tokyo'), ('Asia/Tomsk', 'Asia/Tomsk'), ('Asia/Ulaanbaatar', 'Asia/Ulaanbaatar'), ('Asia/Urumqi', 'Asia/Urumqi'), ('Asia/Ust-Nera', 'Asia/Ust-Nera'), ('Asia/Vientiane', 'Asia/Vientiane'), ('Asia/Vladivostok', 'Asia/Vladivostok'), ('Asia/Yakutsk', 'Asia/Yakutsk'), ('Asia/Yangon', 'Asia/Yangon'), ('Asia/Yekaterinburg', 'Asia/Yekaterinburg'), ('Asia/Yerevan', 'Asia/Yerevan'), ('Atlantic/Azores', 'Atlantic/Azores'), ('Atlantic/Bermuda', 'Atlantic/Bermuda'), ('Atlantic/Canary', 'Atlantic/Canary'), ('Atlantic/Cape_Verde', 'Atlantic/Cape_Verde'), ('Atlantic/Faroe', 'Atlantic/Faroe'), ('Atlantic/Madeira', 'Atlantic/Madeira'), ('Atlantic/Reykjavik', 'Atlantic/Reykjavik'), ('Atlantic/South_Georgia', 'Atlantic/South_Georgia'), ('Atlantic/St_Helena', 'Atlantic/St_Helena'), ('Atlantic/Stanley', 'Atlantic/Stanley'), ('Australia/Adelaide', 'Australia/Adelaide'), ('Australia/Brisbane', 'Australia/Brisbane'), ('Australia/Broken_Hill', 'Australia/Broken_Hill'), ('Australia/Currie', 'Australia/Currie'), ('Australia/Darwin', 'Australia/Darwin'), ('Australia/Eucla', 'Australia/Eucla'), ('Australia/Hobart', 'Australia/Hobart'), ('Australia/Lindeman', 'Australia/Lindeman'), ('Australia/Lord_Howe', 'Australia/Lord_Howe'), ('Australia/Melbourne', 'Australia/Melbourne'), ('Australia/Perth', 'Australia/Perth'), ('Australia/Sydney', 'Australia/Sydney'), ('Canada/Atlantic', 'Canada/Atlantic'), ('Canada/Central', 'Canada/Central'), ('Canada/Eastern', 'Canada/Eastern'), ('Canada/Mountain', 'Canada/Mountain'), ('Canada/Newfoundland', 'Canada/Newfoundland'), ('Canada/Pacific', 'Canada/Pacific'), ('Europe/Amsterdam', 'Europe/Amsterdam'), ('Europe/Andorra', 'Europe/Andorra'), ('Europe/Astrakhan', 'Europe/Astrakhan'), ('Europe/Athens', 'Europe/Athens'), ('Europe/Belgrade', 'Europe/Belgrade'), ('Europe/Berlin', 'Europe/Berlin'), ('Europe/Bratislava', 'Europe/Bratislava'), ('Europe/Brussels', 'Europe/Brussels'), ('Europe/Bucharest', 'Europe/Bucharest'), ('Europe/Budapest', 'Europe/Budapest'), ('Europe/Busingen', 'Europe/Busingen'), ('Europe/Chisinau', 'Europe/Chisinau'), ('Europe/Copenhagen', 'Europe/Copenhagen'), ('Europe/Dublin', 'Europe/Dublin'), ('Europe/Gibraltar', 'Europe/Gibraltar'), ('Europe/Guernsey', 'Europe/Guernsey'), ('Europe/Helsinki', 'Europe/Helsinki'), ('Europe/Isle_of_Man', 'Europe/Isle_of_Man'), ('Europe/Istanbul', 'Europe/Istanbul'), ('Europe/Jersey', 'Europe/Jersey'), ('Europe/Kaliningrad', 'Europe/Kaliningrad'), ('Europe/Kiev', 'Europe/Kiev'), ('Europe/Kirov', 'Europe/Kirov'), ('Europe/Lisbon', 'Europe/Lisbon'), ('Europe/Ljubljana', 'Europe/Ljubljana'), ('Europe/London', 'Europe/London'), ('Europe/Luxembourg', 'Europe/Luxembourg'), ('Europe/Madrid', 'Europe/Madrid'), ('Europe/Malta', 'Europe/Malta'), ('Europe/Mariehamn', 'Europe/Mariehamn'), ('Europe/Minsk', 'Europe/Minsk'), ('Europe/Monaco', 'Europe/Monaco'), ('Europe/Moscow', 'Europe/Moscow'), ('Europe/Oslo', 'Europe/Oslo'), ('Europe/Paris', 'Europe/Paris'), ('Europe/Podgorica', 'Europe/Podgorica'), ('Europe/Prague', 'Europe/Prague'), ('Europe/Riga', 'Europe/Riga'), ('Europe/Rome', 'Europe/Rome'), ('Europe/Samara', 'Europe/Samara'), ('Europe/San_Marino', 'Europe/San_Marino'), ('Europe/Sarajevo', 'Europe/Sarajevo'), ('Europe/Saratov', 'Europe/Saratov'), ('Europe/Simferopol', 'Europe/Simferopol'), ('Europe/Skopje', 'Europe/Skopje'), ('Europe/Sofia', 'Europe/Sofia'), ('Europe/Stockholm', 'Europe/Stockholm'), ('Europe/Tallinn', 'Europe/Tallinn'), ('Europe/Tirane', 'Europe/Tirane'), ('Europe/Ulyanovsk', 'Europe/Ulyanovsk'), ('Europe/Uzhgorod', 'Europe/Uzhgorod'), ('Europe/Vaduz', 'Europe/Vaduz'), ('Europe/Vatican', 'Europe/Vatican'), ('Europe/Vienna', 'Europe/Vienna'), ('Europe/Vilnius', 'Europe/Vilnius'), ('Europe/Volgograd', 'Europe/Volgograd'), ('Europe/Warsaw', 'Europe/Warsaw'), ('Europe/Zagreb', 'Europe/Zagreb'), ('Europe/Zaporozhye', 'Europe/Zaporozhye'), ('Europe/Zurich', 'Europe/Zurich'), ('GMT', 'GMT'), ('Indian/Antananarivo', 'Indian/Antananarivo'), ('Indian/Chagos', 'Indian/Chagos'), ('Indian/Christmas', 'Indian/Christmas'), ('Indian/Cocos', 'Indian/Cocos'), ('Indian/Comoro', 'Indian/Comoro'), ('Indian/Kerguelen', 'Indian/Kerguelen'), ('Indian/Mahe', 'Indian/Mahe'), ('Indian/Maldives', 'Indian/Maldives'), ('Indian/Mauritius', 'Indian/Mauritius'), ('Indian/Mayotte', 'Indian/Mayotte'), ('Indian/Reunion', 'Indian/Reunion'), ('Pacific/Apia', 'Pacific/Apia'), ('Pacific/Auckland', 'Pacific/Auckland'), ('Pacific/Bougainville', 'Pacific/Bougainville'), ('Pacific/Chatham', 'Pacific/Chatham'), ('Pacific/Chuuk', 'Pacific/Chuuk'), ('Pacific/Easter', 'Pacific/Easter'), ('Pacific/Efate', 'Pacific/Efate'), ('Pacific/Enderbury', 'Pacific/Enderbury'), ('Pacific/Fakaofo', 'Pacific/Fakaofo'), ('Pacific/Fiji', 'Pacific/Fiji'), ('Pacific/Funafuti', 'Pacific/Funafuti'), ('Pacific/Galapagos', 'Pacific/Galapagos'), ('Pacific/Gambier', 'Pacific/Gambier'), ('Pacific/Guadalcanal', 'Pacific/Guadalcanal'), ('Pacific/Guam', 'Pacific/Guam'), ('Pacific/Honolulu', 'Pacific/Honolulu'), ('Pacific/Kiritimati', 'Pacific/Kiritimati'), ('Pacific/Kosrae', 'Pacific/Kosrae'), ('Pacific/Kwajalein', 'Pacific/Kwajalein'), ('Pacific/Majuro', 'Pacific/Majuro'), ('Pacific/Marquesas', 'Pacific/Marquesas'), ('Pacific/Midway', 'Pacific/Midway'), ('Pacific/Nauru', 'Pacific/Nauru'), ('Pacific/Niue', 'Pacific/Niue'), ('Pacific/Norfolk', 'Pacific/Norfolk'), ('Pacific/Noumea', 'Pacific/Noumea'), ('Pacific/Pago_Pago', 'Pacific/Pago_Pago'), ('Pacific/Palau', 'Pacific/Palau'), ('Pacific/Pitcairn', 'Pacific/Pitcairn'), ('Pacific/Pohnpei', 'Pacific/Pohnpei'), ('Pacific/Port_Moresby', 'Pacific/Port_Moresby'), ('Pacific/Rarotonga', 'Pacific/Rarotonga'), ('Pacific/Saipan', 'Pacific/Saipan'), ('Pacific/Tahiti', 'Pacific/Tahiti'), ('Pacific/Tarawa', 'Pacific/Tarawa'), ('Pacific/Tongatapu', 'Pacific/Tongatapu'), ('Pacific/Wake', 'Pacific/Wake'), ('Pacific/Wallis', 'Pacific/Wallis'), ('US/Alaska', 'US/Alaska'), ('US/Arizona', 'US/Arizona'), ('US/Central', 'US/Central'), ('US/Eastern', 'US/Eastern'), ('US/Hawaii', 'US/Hawaii'), ('US/Mountain', 'US/Mountain'), ('US/Pacific', 'US/Pacific'), ('UTC', 'UTC')], default=b'UTC', help_text=b'Used for developer clock page', max_length=100)),
+ ('notify', models.BooleanField(
+ default=True, help_text="When enabled, send user 'flag out-of-date' notifications",
+ verbose_name='Send notifications')),
+ ('time_zone', models.CharField(
+ choices=[
+ ('Africa/Abidjan', 'Africa/Abidjan'),
+ ('Africa/Accra', 'Africa/Accra'),
+ ('Africa/Addis_Ababa', 'Africa/Addis_Ababa'),
+ ('Africa/Algiers', 'Africa/Algiers'),
+ ('Africa/Asmara', 'Africa/Asmara'),
+ ('Africa/Bamako', 'Africa/Bamako'),
+ ('Africa/Bangui', 'Africa/Bangui'),
+ ('Africa/Banjul', 'Africa/Banjul'),
+ ('Africa/Bissau', 'Africa/Bissau'),
+ ('Africa/Blantyre', 'Africa/Blantyre'),
+ ('Africa/Brazzaville', 'Africa/Brazzaville'),
+ ('Africa/Bujumbura', 'Africa/Bujumbura'),
+ ('Africa/Cairo', 'Africa/Cairo'),
+ ('Africa/Casablanca', 'Africa/Casablanca'),
+ ('Africa/Ceuta', 'Africa/Ceuta'),
+ ('Africa/Conakry', 'Africa/Conakry'),
+ ('Africa/Dakar', 'Africa/Dakar'),
+ ('Africa/Dar_es_Salaam', 'Africa/Dar_es_Salaam'),
+ ('Africa/Djibouti', 'Africa/Djibouti'),
+ ('Africa/Douala', 'Africa/Douala'),
+ ('Africa/El_Aaiun', 'Africa/El_Aaiun'),
+ ('Africa/Freetown', 'Africa/Freetown'),
+ ('Africa/Gaborone', 'Africa/Gaborone'),
+ ('Africa/Harare', 'Africa/Harare'),
+ ('Africa/Johannesburg', 'Africa/Johannesburg'),
+ ('Africa/Juba', 'Africa/Juba'),
+ ('Africa/Kampala', 'Africa/Kampala'),
+ ('Africa/Khartoum', 'Africa/Khartoum'),
+ ('Africa/Kigali', 'Africa/Kigali'),
+ ('Africa/Kinshasa', 'Africa/Kinshasa'),
+ ('Africa/Lagos', 'Africa/Lagos'),
+ ('Africa/Libreville', 'Africa/Libreville'),
+ ('Africa/Lome', 'Africa/Lome'),
+ ('Africa/Luanda', 'Africa/Luanda'),
+ ('Africa/Lubumbashi', 'Africa/Lubumbashi'),
+ ('Africa/Lusaka', 'Africa/Lusaka'),
+ ('Africa/Malabo', 'Africa/Malabo'),
+ ('Africa/Maputo', 'Africa/Maputo'),
+ ('Africa/Maseru', 'Africa/Maseru'),
+ ('Africa/Mbabane', 'Africa/Mbabane'),
+ ('Africa/Mogadishu', 'Africa/Mogadishu'),
+ ('Africa/Monrovia', 'Africa/Monrovia'),
+ ('Africa/Nairobi', 'Africa/Nairobi'),
+ ('Africa/Ndjamena', 'Africa/Ndjamena'),
+ ('Africa/Niamey', 'Africa/Niamey'),
+ ('Africa/Nouakchott', 'Africa/Nouakchott'),
+ ('Africa/Ouagadougou', 'Africa/Ouagadougou'),
+ ('Africa/Porto-Novo', 'Africa/Porto-Novo'),
+ ('Africa/Sao_Tome', 'Africa/Sao_Tome'),
+ ('Africa/Tripoli', 'Africa/Tripoli'),
+ ('Africa/Tunis', 'Africa/Tunis'),
+ ('Africa/Windhoek', 'Africa/Windhoek'),
+ ('America/Adak', 'America/Adak'),
+ ('America/Anchorage', 'America/Anchorage'),
+ ('America/Anguilla', 'America/Anguilla'),
+ ('America/Antigua', 'America/Antigua'),
+ ('America/Araguaina', 'America/Araguaina'),
+ ('America/Argentina/Buenos_Aires', 'America/Argentina/Buenos_Aires'),
+ ('America/Argentina/Catamarca', 'America/Argentina/Catamarca'),
+ ('America/Argentina/Cordoba', 'America/Argentina/Cordoba'),
+ ('America/Argentina/Jujuy', 'America/Argentina/Jujuy'),
+ ('America/Argentina/La_Rioja', 'America/Argentina/La_Rioja'),
+ ('America/Argentina/Mendoza', 'America/Argentina/Mendoza'),
+ ('America/Argentina/Rio_Gallegos', 'America/Argentina/Rio_Gallegos'),
+ ('America/Argentina/Salta', 'America/Argentina/Salta'),
+ ('America/Argentina/San_Juan', 'America/Argentina/San_Juan'),
+ ('America/Argentina/San_Luis', 'America/Argentina/San_Luis'),
+ ('America/Argentina/Tucuman', 'America/Argentina/Tucuman'),
+ ('America/Argentina/Ushuaia', 'America/Argentina/Ushuaia'),
+ ('America/Aruba', 'America/Aruba'),
+ ('America/Asuncion', 'America/Asuncion'),
+ ('America/Atikokan', 'America/Atikokan'),
+ ('America/Bahia', 'America/Bahia'),
+ ('America/Bahia_Banderas', 'America/Bahia_Banderas'),
+ ('America/Barbados', 'America/Barbados'),
+ ('America/Belem', 'America/Belem'),
+ ('America/Belize', 'America/Belize'),
+ ('America/Blanc-Sablon', 'America/Blanc-Sablon'),
+ ('America/Boa_Vista', 'America/Boa_Vista'),
+ ('America/Bogota', 'America/Bogota'),
+ ('America/Boise', 'America/Boise'),
+ ('America/Cambridge_Bay', 'America/Cambridge_Bay'),
+ ('America/Campo_Grande', 'America/Campo_Grande'),
+ ('America/Cancun', 'America/Cancun'),
+ ('America/Caracas', 'America/Caracas'),
+ ('America/Cayenne', 'America/Cayenne'),
+ ('America/Cayman', 'America/Cayman'),
+ ('America/Chicago', 'America/Chicago'),
+ ('America/Chihuahua', 'America/Chihuahua'),
+ ('America/Costa_Rica', 'America/Costa_Rica'),
+ ('America/Creston', 'America/Creston'),
+ ('America/Cuiaba', 'America/Cuiaba'),
+ ('America/Curacao', 'America/Curacao'),
+ ('America/Danmarkshavn', 'America/Danmarkshavn'),
+ ('America/Dawson', 'America/Dawson'),
+ ('America/Dawson_Creek', 'America/Dawson_Creek'),
+ ('America/Denver', 'America/Denver'),
+ ('America/Detroit', 'America/Detroit'),
+ ('America/Dominica', 'America/Dominica'),
+ ('America/Edmonton', 'America/Edmonton'),
+ ('America/Eirunepe', 'America/Eirunepe'),
+ ('America/El_Salvador', 'America/El_Salvador'),
+ ('America/Fort_Nelson', 'America/Fort_Nelson'),
+ ('America/Fortaleza', 'America/Fortaleza'),
+ ('America/Glace_Bay', 'America/Glace_Bay'),
+ ('America/Godthab', 'America/Godthab'),
+ ('America/Goose_Bay', 'America/Goose_Bay'),
+ ('America/Grand_Turk', 'America/Grand_Turk'),
+ ('America/Grenada', 'America/Grenada'),
+ ('America/Guadeloupe', 'America/Guadeloupe'),
+ ('America/Guatemala', 'America/Guatemala'),
+ ('America/Guayaquil', 'America/Guayaquil'),
+ ('America/Guyana', 'America/Guyana'),
+ ('America/Halifax', 'America/Halifax'),
+ ('America/Havana', 'America/Havana'),
+ ('America/Hermosillo', 'America/Hermosillo'),
+ ('America/Indiana/Indianapolis', 'America/Indiana/Indianapolis'),
+ ('America/Indiana/Knox', 'America/Indiana/Knox'),
+ ('America/Indiana/Marengo', 'America/Indiana/Marengo'),
+ ('America/Indiana/Petersburg', 'America/Indiana/Petersburg'),
+ ('America/Indiana/Tell_City', 'America/Indiana/Tell_City'),
+ ('America/Indiana/Vevay', 'America/Indiana/Vevay'),
+ ('America/Indiana/Vincennes', 'America/Indiana/Vincennes'),
+ ('America/Indiana/Winamac', 'America/Indiana/Winamac'),
+ ('America/Inuvik', 'America/Inuvik'),
+ ('America/Iqaluit', 'America/Iqaluit'),
+ ('America/Jamaica', 'America/Jamaica'),
+ ('America/Juneau', 'America/Juneau'),
+ ('America/Kentucky/Louisville', 'America/Kentucky/Louisville'),
+ ('America/Kentucky/Monticello', 'America/Kentucky/Monticello'),
+ ('America/Kralendijk', 'America/Kralendijk'),
+ ('America/La_Paz', 'America/La_Paz'),
+ ('America/Lima', 'America/Lima'),
+ ('America/Los_Angeles', 'America/Los_Angeles'),
+ ('America/Lower_Princes', 'America/Lower_Princes'),
+ ('America/Maceio', 'America/Maceio'),
+ ('America/Managua', 'America/Managua'),
+ ('America/Manaus', 'America/Manaus'),
+ ('America/Marigot', 'America/Marigot'),
+ ('America/Martinique', 'America/Martinique'),
+ ('America/Matamoros', 'America/Matamoros'),
+ ('America/Mazatlan', 'America/Mazatlan'),
+ ('America/Menominee', 'America/Menominee'),
+ ('America/Merida', 'America/Merida'),
+ ('America/Metlakatla', 'America/Metlakatla'),
+ ('America/Mexico_City', 'America/Mexico_City'),
+ ('America/Miquelon', 'America/Miquelon'),
+ ('America/Moncton', 'America/Moncton'),
+ ('America/Monterrey', 'America/Monterrey'),
+ ('America/Montevideo', 'America/Montevideo'),
+ ('America/Montserrat', 'America/Montserrat'),
+ ('America/Nassau', 'America/Nassau'),
+ ('America/New_York', 'America/New_York'),
+ ('America/Nipigon', 'America/Nipigon'),
+ ('America/Nome', 'America/Nome'),
+ ('America/Noronha', 'America/Noronha'),
+ ('America/North_Dakota/Beulah', 'America/North_Dakota/Beulah'),
+ ('America/North_Dakota/Center', 'America/North_Dakota/Center'),
+ ('America/North_Dakota/New_Salem', 'America/North_Dakota/New_Salem'),
+ ('America/Ojinaga', 'America/Ojinaga'),
+ ('America/Panama', 'America/Panama'),
+ ('America/Pangnirtung', 'America/Pangnirtung'),
+ ('America/Paramaribo', 'America/Paramaribo'),
+ ('America/Phoenix', 'America/Phoenix'),
+ ('America/Port-au-Prince', 'America/Port-au-Prince'),
+ ('America/Port_of_Spain', 'America/Port_of_Spain'),
+ ('America/Porto_Velho', 'America/Porto_Velho'),
+ ('America/Puerto_Rico', 'America/Puerto_Rico'),
+ ('America/Punta_Arenas', 'America/Punta_Arenas'),
+ ('America/Rainy_River', 'America/Rainy_River'),
+ ('America/Rankin_Inlet', 'America/Rankin_Inlet'),
+ ('America/Recife', 'America/Recife'),
+ ('America/Regina', 'America/Regina'),
+ ('America/Resolute', 'America/Resolute'),
+ ('America/Rio_Branco', 'America/Rio_Branco'),
+ ('America/Santarem', 'America/Santarem'),
+ ('America/Santiago', 'America/Santiago'),
+ ('America/Santo_Domingo', 'America/Santo_Domingo'),
+ ('America/Sao_Paulo', 'America/Sao_Paulo'),
+ ('America/Scoresbysund', 'America/Scoresbysund'),
+ ('America/Sitka', 'America/Sitka'),
+ ('America/St_Barthelemy', 'America/St_Barthelemy'),
+ ('America/St_Johns', 'America/St_Johns'),
+ ('America/St_Kitts', 'America/St_Kitts'),
+ ('America/St_Lucia', 'America/St_Lucia'),
+ ('America/St_Thomas', 'America/St_Thomas'),
+ ('America/St_Vincent', 'America/St_Vincent'),
+ ('America/Swift_Current', 'America/Swift_Current'),
+ ('America/Tegucigalpa', 'America/Tegucigalpa'),
+ ('America/Thule', 'America/Thule'),
+ ('America/Thunder_Bay', 'America/Thunder_Bay'),
+ ('America/Tijuana', 'America/Tijuana'),
+ ('America/Toronto', 'America/Toronto'),
+ ('America/Tortola', 'America/Tortola'),
+ ('America/Vancouver', 'America/Vancouver'),
+ ('America/Whitehorse', 'America/Whitehorse'),
+ ('America/Winnipeg', 'America/Winnipeg'),
+ ('America/Yakutat', 'America/Yakutat'),
+ ('America/Yellowknife', 'America/Yellowknife'),
+ ('Antarctica/Casey', 'Antarctica/Casey'),
+ ('Antarctica/Davis', 'Antarctica/Davis'),
+ ('Antarctica/DumontDUrville', 'Antarctica/DumontDUrville'),
+ ('Antarctica/Macquarie', 'Antarctica/Macquarie'),
+ ('Antarctica/Mawson', 'Antarctica/Mawson'),
+ ('Antarctica/McMurdo', 'Antarctica/McMurdo'),
+ ('Antarctica/Palmer', 'Antarctica/Palmer'),
+ ('Antarctica/Rothera', 'Antarctica/Rothera'),
+ ('Antarctica/Syowa', 'Antarctica/Syowa'),
+ ('Antarctica/Troll', 'Antarctica/Troll'),
+ ('Antarctica/Vostok', 'Antarctica/Vostok'),
+ ('Arctic/Longyearbyen', 'Arctic/Longyearbyen'),
+ ('Asia/Aden', 'Asia/Aden'),
+ ('Asia/Almaty', 'Asia/Almaty'),
+ ('Asia/Amman', 'Asia/Amman'),
+ ('Asia/Anadyr', 'Asia/Anadyr'),
+ ('Asia/Aqtau', 'Asia/Aqtau'),
+ ('Asia/Aqtobe', 'Asia/Aqtobe'),
+ ('Asia/Ashgabat', 'Asia/Ashgabat'),
+ ('Asia/Atyrau', 'Asia/Atyrau'),
+ ('Asia/Baghdad', 'Asia/Baghdad'),
+ ('Asia/Bahrain', 'Asia/Bahrain'),
+ ('Asia/Baku', 'Asia/Baku'),
+ ('Asia/Bangkok', 'Asia/Bangkok'),
+ ('Asia/Barnaul', 'Asia/Barnaul'),
+ ('Asia/Beirut', 'Asia/Beirut'),
+ ('Asia/Bishkek', 'Asia/Bishkek'),
+ ('Asia/Brunei', 'Asia/Brunei'),
+ ('Asia/Chita', 'Asia/Chita'),
+ ('Asia/Choibalsan', 'Asia/Choibalsan'),
+ ('Asia/Colombo', 'Asia/Colombo'),
+ ('Asia/Damascus', 'Asia/Damascus'),
+ ('Asia/Dhaka', 'Asia/Dhaka'),
+ ('Asia/Dili', 'Asia/Dili'),
+ ('Asia/Dubai', 'Asia/Dubai'),
+ ('Asia/Dushanbe', 'Asia/Dushanbe'),
+ ('Asia/Famagusta', 'Asia/Famagusta'),
+ ('Asia/Gaza', 'Asia/Gaza'),
+ ('Asia/Hebron', 'Asia/Hebron'),
+ ('Asia/Ho_Chi_Minh', 'Asia/Ho_Chi_Minh'),
+ ('Asia/Hong_Kong', 'Asia/Hong_Kong'),
+ ('Asia/Hovd', 'Asia/Hovd'),
+ ('Asia/Irkutsk', 'Asia/Irkutsk'),
+ ('Asia/Jakarta', 'Asia/Jakarta'),
+ ('Asia/Jayapura', 'Asia/Jayapura'),
+ ('Asia/Jerusalem', 'Asia/Jerusalem'),
+ ('Asia/Kabul', 'Asia/Kabul'),
+ ('Asia/Kamchatka', 'Asia/Kamchatka'),
+ ('Asia/Karachi', 'Asia/Karachi'),
+ ('Asia/Kathmandu', 'Asia/Kathmandu'),
+ ('Asia/Khandyga', 'Asia/Khandyga'),
+ ('Asia/Kolkata', 'Asia/Kolkata'),
+ ('Asia/Krasnoyarsk', 'Asia/Krasnoyarsk'),
+ ('Asia/Kuala_Lumpur', 'Asia/Kuala_Lumpur'),
+ ('Asia/Kuching', 'Asia/Kuching'),
+ ('Asia/Kuwait', 'Asia/Kuwait'),
+ ('Asia/Macau', 'Asia/Macau'),
+ ('Asia/Magadan', 'Asia/Magadan'),
+ ('Asia/Makassar', 'Asia/Makassar'),
+ ('Asia/Manila', 'Asia/Manila'),
+ ('Asia/Muscat', 'Asia/Muscat'),
+ ('Asia/Nicosia', 'Asia/Nicosia'),
+ ('Asia/Novokuznetsk', 'Asia/Novokuznetsk'),
+ ('Asia/Novosibirsk', 'Asia/Novosibirsk'),
+ ('Asia/Omsk', 'Asia/Omsk'),
+ ('Asia/Oral', 'Asia/Oral'),
+ ('Asia/Phnom_Penh', 'Asia/Phnom_Penh'),
+ ('Asia/Pontianak', 'Asia/Pontianak'),
+ ('Asia/Pyongyang', 'Asia/Pyongyang'),
+ ('Asia/Qatar', 'Asia/Qatar'),
+ ('Asia/Qyzylorda', 'Asia/Qyzylorda'),
+ ('Asia/Riyadh', 'Asia/Riyadh'),
+ ('Asia/Sakhalin', 'Asia/Sakhalin'),
+ ('Asia/Samarkand', 'Asia/Samarkand'),
+ ('Asia/Seoul', 'Asia/Seoul'),
+ ('Asia/Shanghai', 'Asia/Shanghai'),
+ ('Asia/Singapore', 'Asia/Singapore'),
+ ('Asia/Srednekolymsk', 'Asia/Srednekolymsk'),
+ ('Asia/Taipei', 'Asia/Taipei'),
+ ('Asia/Tashkent', 'Asia/Tashkent'),
+ ('Asia/Tbilisi', 'Asia/Tbilisi'),
+ ('Asia/Tehran', 'Asia/Tehran'),
+ ('Asia/Thimphu', 'Asia/Thimphu'),
+ ('Asia/Tokyo', 'Asia/Tokyo'),
+ ('Asia/Tomsk', 'Asia/Tomsk'),
+ ('Asia/Ulaanbaatar', 'Asia/Ulaanbaatar'),
+ ('Asia/Urumqi', 'Asia/Urumqi'),
+ ('Asia/Ust-Nera', 'Asia/Ust-Nera'),
+ ('Asia/Vientiane', 'Asia/Vientiane'),
+ ('Asia/Vladivostok', 'Asia/Vladivostok'),
+ ('Asia/Yakutsk', 'Asia/Yakutsk'),
+ ('Asia/Yangon', 'Asia/Yangon'),
+ ('Asia/Yekaterinburg', 'Asia/Yekaterinburg'),
+ ('Asia/Yerevan', 'Asia/Yerevan'),
+ ('Atlantic/Azores', 'Atlantic/Azores'),
+ ('Atlantic/Bermuda', 'Atlantic/Bermuda'),
+ ('Atlantic/Canary', 'Atlantic/Canary'),
+ ('Atlantic/Cape_Verde', 'Atlantic/Cape_Verde'),
+ ('Atlantic/Faroe', 'Atlantic/Faroe'),
+ ('Atlantic/Madeira', 'Atlantic/Madeira'),
+ ('Atlantic/Reykjavik', 'Atlantic/Reykjavik'),
+ ('Atlantic/South_Georgia', 'Atlantic/South_Georgia'),
+ ('Atlantic/St_Helena', 'Atlantic/St_Helena'),
+ ('Atlantic/Stanley', 'Atlantic/Stanley'),
+ ('Australia/Adelaide', 'Australia/Adelaide'),
+ ('Australia/Brisbane', 'Australia/Brisbane'),
+ ('Australia/Broken_Hill', 'Australia/Broken_Hill'),
+ ('Australia/Currie', 'Australia/Currie'),
+ ('Australia/Darwin', 'Australia/Darwin'),
+ ('Australia/Eucla', 'Australia/Eucla'),
+ ('Australia/Hobart', 'Australia/Hobart'),
+ ('Australia/Lindeman', 'Australia/Lindeman'),
+ ('Australia/Lord_Howe', 'Australia/Lord_Howe'),
+ ('Australia/Melbourne', 'Australia/Melbourne'),
+ ('Australia/Perth', 'Australia/Perth'),
+ ('Australia/Sydney', 'Australia/Sydney'),
+ ('Canada/Atlantic', 'Canada/Atlantic'),
+ ('Canada/Central', 'Canada/Central'),
+ ('Canada/Eastern', 'Canada/Eastern'),
+ ('Canada/Mountain', 'Canada/Mountain'),
+ ('Canada/Newfoundland', 'Canada/Newfoundland'),
+ ('Canada/Pacific', 'Canada/Pacific'),
+ ('Europe/Amsterdam', 'Europe/Amsterdam'),
+ ('Europe/Andorra', 'Europe/Andorra'),
+ ('Europe/Astrakhan', 'Europe/Astrakhan'),
+ ('Europe/Athens', 'Europe/Athens'),
+ ('Europe/Belgrade', 'Europe/Belgrade'),
+ ('Europe/Berlin', 'Europe/Berlin'),
+ ('Europe/Bratislava', 'Europe/Bratislava'),
+ ('Europe/Brussels', 'Europe/Brussels'),
+ ('Europe/Bucharest', 'Europe/Bucharest'),
+ ('Europe/Budapest', 'Europe/Budapest'),
+ ('Europe/Busingen', 'Europe/Busingen'),
+ ('Europe/Chisinau', 'Europe/Chisinau'),
+ ('Europe/Copenhagen', 'Europe/Copenhagen'),
+ ('Europe/Dublin', 'Europe/Dublin'),
+ ('Europe/Gibraltar', 'Europe/Gibraltar'),
+ ('Europe/Guernsey', 'Europe/Guernsey'),
+ ('Europe/Helsinki', 'Europe/Helsinki'),
+ ('Europe/Isle_of_Man', 'Europe/Isle_of_Man'),
+ ('Europe/Istanbul', 'Europe/Istanbul'),
+ ('Europe/Jersey', 'Europe/Jersey'),
+ ('Europe/Kaliningrad', 'Europe/Kaliningrad'),
+ ('Europe/Kiev', 'Europe/Kiev'),
+ ('Europe/Kirov', 'Europe/Kirov'),
+ ('Europe/Lisbon', 'Europe/Lisbon'),
+ ('Europe/Ljubljana', 'Europe/Ljubljana'),
+ ('Europe/London', 'Europe/London'),
+ ('Europe/Luxembourg', 'Europe/Luxembourg'),
+ ('Europe/Madrid', 'Europe/Madrid'),
+ ('Europe/Malta', 'Europe/Malta'),
+ ('Europe/Mariehamn', 'Europe/Mariehamn'),
+ ('Europe/Minsk', 'Europe/Minsk'),
+ ('Europe/Monaco', 'Europe/Monaco'),
+ ('Europe/Moscow', 'Europe/Moscow'),
+ ('Europe/Oslo', 'Europe/Oslo'),
+ ('Europe/Paris', 'Europe/Paris'),
+ ('Europe/Podgorica', 'Europe/Podgorica'),
+ ('Europe/Prague', 'Europe/Prague'),
+ ('Europe/Riga', 'Europe/Riga'),
+ ('Europe/Rome', 'Europe/Rome'),
+ ('Europe/Samara', 'Europe/Samara'),
+ ('Europe/San_Marino', 'Europe/San_Marino'),
+ ('Europe/Sarajevo', 'Europe/Sarajevo'),
+ ('Europe/Saratov', 'Europe/Saratov'),
+ ('Europe/Simferopol', 'Europe/Simferopol'),
+ ('Europe/Skopje', 'Europe/Skopje'),
+ ('Europe/Sofia', 'Europe/Sofia'),
+ ('Europe/Stockholm', 'Europe/Stockholm'),
+ ('Europe/Tallinn', 'Europe/Tallinn'),
+ ('Europe/Tirane', 'Europe/Tirane'),
+ ('Europe/Ulyanovsk', 'Europe/Ulyanovsk'),
+ ('Europe/Uzhgorod', 'Europe/Uzhgorod'),
+ ('Europe/Vaduz', 'Europe/Vaduz'),
+ ('Europe/Vatican', 'Europe/Vatican'),
+ ('Europe/Vienna', 'Europe/Vienna'),
+ ('Europe/Vilnius', 'Europe/Vilnius'),
+ ('Europe/Volgograd', 'Europe/Volgograd'),
+ ('Europe/Warsaw', 'Europe/Warsaw'),
+ ('Europe/Zagreb', 'Europe/Zagreb'),
+ ('Europe/Zaporozhye', 'Europe/Zaporozhye'),
+ ('Europe/Zurich', 'Europe/Zurich'),
+ ('GMT', 'GMT'),
+ ('Indian/Antananarivo', 'Indian/Antananarivo'),
+ ('Indian/Chagos', 'Indian/Chagos'),
+ ('Indian/Christmas', 'Indian/Christmas'),
+ ('Indian/Cocos', 'Indian/Cocos'),
+ ('Indian/Comoro', 'Indian/Comoro'),
+ ('Indian/Kerguelen', 'Indian/Kerguelen'),
+ ('Indian/Mahe', 'Indian/Mahe'),
+ ('Indian/Maldives', 'Indian/Maldives'),
+ ('Indian/Mauritius', 'Indian/Mauritius'),
+ ('Indian/Mayotte', 'Indian/Mayotte'),
+ ('Indian/Reunion', 'Indian/Reunion'),
+ ('Pacific/Apia', 'Pacific/Apia'),
+ ('Pacific/Auckland', 'Pacific/Auckland'),
+ ('Pacific/Bougainville', 'Pacific/Bougainville'),
+ ('Pacific/Chatham', 'Pacific/Chatham'),
+ ('Pacific/Chuuk', 'Pacific/Chuuk'),
+ ('Pacific/Easter', 'Pacific/Easter'),
+ ('Pacific/Efate', 'Pacific/Efate'),
+ ('Pacific/Enderbury', 'Pacific/Enderbury'),
+ ('Pacific/Fakaofo', 'Pacific/Fakaofo'),
+ ('Pacific/Fiji', 'Pacific/Fiji'),
+ ('Pacific/Funafuti', 'Pacific/Funafuti'),
+ ('Pacific/Galapagos', 'Pacific/Galapagos'),
+ ('Pacific/Gambier', 'Pacific/Gambier'),
+ ('Pacific/Guadalcanal', 'Pacific/Guadalcanal'),
+ ('Pacific/Guam', 'Pacific/Guam'),
+ ('Pacific/Honolulu', 'Pacific/Honolulu'),
+ ('Pacific/Kiritimati', 'Pacific/Kiritimati'),
+ ('Pacific/Kosrae', 'Pacific/Kosrae'),
+ ('Pacific/Kwajalein', 'Pacific/Kwajalein'),
+ ('Pacific/Majuro', 'Pacific/Majuro'),
+ ('Pacific/Marquesas', 'Pacific/Marquesas'),
+ ('Pacific/Midway', 'Pacific/Midway'),
+ ('Pacific/Nauru', 'Pacific/Nauru'),
+ ('Pacific/Niue', 'Pacific/Niue'),
+ ('Pacific/Norfolk', 'Pacific/Norfolk'),
+ ('Pacific/Noumea', 'Pacific/Noumea'),
+ ('Pacific/Pago_Pago', 'Pacific/Pago_Pago'),
+ ('Pacific/Palau', 'Pacific/Palau'),
+ ('Pacific/Pitcairn', 'Pacific/Pitcairn'),
+ ('Pacific/Pohnpei', 'Pacific/Pohnpei'),
+ ('Pacific/Port_Moresby', 'Pacific/Port_Moresby'),
+ ('Pacific/Rarotonga', 'Pacific/Rarotonga'),
+ ('Pacific/Saipan', 'Pacific/Saipan'),
+ ('Pacific/Tahiti', 'Pacific/Tahiti'),
+ ('Pacific/Tarawa', 'Pacific/Tarawa'),
+ ('Pacific/Tongatapu', 'Pacific/Tongatapu'),
+ ('Pacific/Wake', 'Pacific/Wake'),
+ ('Pacific/Wallis', 'Pacific/Wallis'),
+ ('US/Alaska', 'US/Alaska'),
+ ('US/Arizona', 'US/Arizona'),
+ ('US/Central', 'US/Central'),
+ ('US/Eastern', 'US/Eastern'),
+ ('US/Hawaii', 'US/Hawaii'),
+ ('US/Mountain', 'US/Mountain'),
+ ('US/Pacific', 'US/Pacific'),
+ ('UTC', 'UTC')],
+ default=b'UTC',
+ help_text=b'Used for developer clock page',
+ max_length=100)),
('alias', models.CharField(help_text='Required field', max_length=50)),
('public_email', models.CharField(help_text='Required field', max_length=50)),
('other_contact', models.CharField(blank=True, max_length=100, null=True)),
- ('pgp_key', devel.fields.PGPKeyField(blank=True, help_text='consists of 40 hex digits; use `gpg --fingerprint`', max_length=40, null=True, verbose_name='PGP key fingerprint')),
+ ('pgp_key', devel.fields.PGPKeyField(
+ blank=True, help_text='consists of 40 hex digits; use `gpg --fingerprint`',
+ max_length=40, null=True, verbose_name='PGP key fingerprint')),
('website', models.CharField(blank=True, max_length=200, null=True)),
('yob', models.IntegerField(blank=True, null=True, verbose_name='Year of birth')),
('country', django_countries.fields.CountryField(blank=True, max_length=2)),
@@ -82,11 +543,16 @@ class Migration(migrations.Migration):
('occupation', models.CharField(blank=True, max_length=50, null=True)),
('roles', models.CharField(blank=True, max_length=255, null=True)),
('favorite_distros', models.CharField(blank=True, max_length=255, null=True)),
- ('picture', models.FileField(default='devs/silhouette.png', help_text='Ideally 125px by 125px', upload_to='devs')),
- ('latin_name', models.CharField(blank=True, help_text='Latin-form name; used only for non-Latin full names', max_length=255, null=True)),
+ ('picture', models.FileField(
+ default='devs/silhouette.png', help_text='Ideally 125px by 125px', upload_to='devs')),
+ ('latin_name', models.CharField(
+ blank=True, help_text='Latin-form name; used only for non-Latin full names',
+ max_length=255, null=True)),
('last_modified', models.DateTimeField(editable=False)),
('allowed_repos', models.ManyToManyField(blank=True, to='main.Repo')),
- ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='userprofile', to=settings.AUTH_USER_MODEL)),
+ ('user', models.OneToOneField(
+ on_delete=django.db.models.deletion.CASCADE,
+ related_name='userprofile', to=settings.AUTH_USER_MODEL)),
],
options={
'get_latest_by': 'last_modified',
diff --git a/devel/migrations/0002_auto_20181216_1605.py b/devel/migrations/0002_auto_20181216_1605.py
index 23dd8c6b..9827d0ae 100644
--- a/devel/migrations/0002_auto_20181216_1605.py
+++ b/devel/migrations/0002_auto_20181216_1605.py
@@ -13,6 +13,447 @@ class Migration(migrations.Migration):
migrations.AlterField(
model_name='userprofile',
name='time_zone',
- field=models.CharField(choices=[('Africa/Abidjan', 'Africa/Abidjan'), ('Africa/Accra', 'Africa/Accra'), ('Africa/Addis_Ababa', 'Africa/Addis_Ababa'), ('Africa/Algiers', 'Africa/Algiers'), ('Africa/Asmara', 'Africa/Asmara'), ('Africa/Bamako', 'Africa/Bamako'), ('Africa/Bangui', 'Africa/Bangui'), ('Africa/Banjul', 'Africa/Banjul'), ('Africa/Bissau', 'Africa/Bissau'), ('Africa/Blantyre', 'Africa/Blantyre'), ('Africa/Brazzaville', 'Africa/Brazzaville'), ('Africa/Bujumbura', 'Africa/Bujumbura'), ('Africa/Cairo', 'Africa/Cairo'), ('Africa/Casablanca', 'Africa/Casablanca'), ('Africa/Ceuta', 'Africa/Ceuta'), ('Africa/Conakry', 'Africa/Conakry'), ('Africa/Dakar', 'Africa/Dakar'), ('Africa/Dar_es_Salaam', 'Africa/Dar_es_Salaam'), ('Africa/Djibouti', 'Africa/Djibouti'), ('Africa/Douala', 'Africa/Douala'), ('Africa/El_Aaiun', 'Africa/El_Aaiun'), ('Africa/Freetown', 'Africa/Freetown'), ('Africa/Gaborone', 'Africa/Gaborone'), ('Africa/Harare', 'Africa/Harare'), ('Africa/Johannesburg', 'Africa/Johannesburg'), ('Africa/Juba', 'Africa/Juba'), ('Africa/Kampala', 'Africa/Kampala'), ('Africa/Khartoum', 'Africa/Khartoum'), ('Africa/Kigali', 'Africa/Kigali'), ('Africa/Kinshasa', 'Africa/Kinshasa'), ('Africa/Lagos', 'Africa/Lagos'), ('Africa/Libreville', 'Africa/Libreville'), ('Africa/Lome', 'Africa/Lome'), ('Africa/Luanda', 'Africa/Luanda'), ('Africa/Lubumbashi', 'Africa/Lubumbashi'), ('Africa/Lusaka', 'Africa/Lusaka'), ('Africa/Malabo', 'Africa/Malabo'), ('Africa/Maputo', 'Africa/Maputo'), ('Africa/Maseru', 'Africa/Maseru'), ('Africa/Mbabane', 'Africa/Mbabane'), ('Africa/Mogadishu', 'Africa/Mogadishu'), ('Africa/Monrovia', 'Africa/Monrovia'), ('Africa/Nairobi', 'Africa/Nairobi'), ('Africa/Ndjamena', 'Africa/Ndjamena'), ('Africa/Niamey', 'Africa/Niamey'), ('Africa/Nouakchott', 'Africa/Nouakchott'), ('Africa/Ouagadougou', 'Africa/Ouagadougou'), ('Africa/Porto-Novo', 'Africa/Porto-Novo'), ('Africa/Sao_Tome', 'Africa/Sao_Tome'), ('Africa/Tripoli', 'Africa/Tripoli'), ('Africa/Tunis', 'Africa/Tunis'), ('Africa/Windhoek', 'Africa/Windhoek'), ('America/Adak', 'America/Adak'), ('America/Anchorage', 'America/Anchorage'), ('America/Anguilla', 'America/Anguilla'), ('America/Antigua', 'America/Antigua'), ('America/Araguaina', 'America/Araguaina'), ('America/Argentina/Buenos_Aires', 'America/Argentina/Buenos_Aires'), ('America/Argentina/Catamarca', 'America/Argentina/Catamarca'), ('America/Argentina/Cordoba', 'America/Argentina/Cordoba'), ('America/Argentina/Jujuy', 'America/Argentina/Jujuy'), ('America/Argentina/La_Rioja', 'America/Argentina/La_Rioja'), ('America/Argentina/Mendoza', 'America/Argentina/Mendoza'), ('America/Argentina/Rio_Gallegos', 'America/Argentina/Rio_Gallegos'), ('America/Argentina/Salta', 'America/Argentina/Salta'), ('America/Argentina/San_Juan', 'America/Argentina/San_Juan'), ('America/Argentina/San_Luis', 'America/Argentina/San_Luis'), ('America/Argentina/Tucuman', 'America/Argentina/Tucuman'), ('America/Argentina/Ushuaia', 'America/Argentina/Ushuaia'), ('America/Aruba', 'America/Aruba'), ('America/Asuncion', 'America/Asuncion'), ('America/Atikokan', 'America/Atikokan'), ('America/Bahia', 'America/Bahia'), ('America/Bahia_Banderas', 'America/Bahia_Banderas'), ('America/Barbados', 'America/Barbados'), ('America/Belem', 'America/Belem'), ('America/Belize', 'America/Belize'), ('America/Blanc-Sablon', 'America/Blanc-Sablon'), ('America/Boa_Vista', 'America/Boa_Vista'), ('America/Bogota', 'America/Bogota'), ('America/Boise', 'America/Boise'), ('America/Cambridge_Bay', 'America/Cambridge_Bay'), ('America/Campo_Grande', 'America/Campo_Grande'), ('America/Cancun', 'America/Cancun'), ('America/Caracas', 'America/Caracas'), ('America/Cayenne', 'America/Cayenne'), ('America/Cayman', 'America/Cayman'), ('America/Chicago', 'America/Chicago'), ('America/Chihuahua', 'America/Chihuahua'), ('America/Costa_Rica', 'America/Costa_Rica'), ('America/Creston', 'America/Creston'), ('America/Cuiaba', 'America/Cuiaba'), ('America/Curacao', 'America/Curacao'), ('America/Danmarkshavn', 'America/Danmarkshavn'), ('America/Dawson', 'America/Dawson'), ('America/Dawson_Creek', 'America/Dawson_Creek'), ('America/Denver', 'America/Denver'), ('America/Detroit', 'America/Detroit'), ('America/Dominica', 'America/Dominica'), ('America/Edmonton', 'America/Edmonton'), ('America/Eirunepe', 'America/Eirunepe'), ('America/El_Salvador', 'America/El_Salvador'), ('America/Fort_Nelson', 'America/Fort_Nelson'), ('America/Fortaleza', 'America/Fortaleza'), ('America/Glace_Bay', 'America/Glace_Bay'), ('America/Godthab', 'America/Godthab'), ('America/Goose_Bay', 'America/Goose_Bay'), ('America/Grand_Turk', 'America/Grand_Turk'), ('America/Grenada', 'America/Grenada'), ('America/Guadeloupe', 'America/Guadeloupe'), ('America/Guatemala', 'America/Guatemala'), ('America/Guayaquil', 'America/Guayaquil'), ('America/Guyana', 'America/Guyana'), ('America/Halifax', 'America/Halifax'), ('America/Havana', 'America/Havana'), ('America/Hermosillo', 'America/Hermosillo'), ('America/Indiana/Indianapolis', 'America/Indiana/Indianapolis'), ('America/Indiana/Knox', 'America/Indiana/Knox'), ('America/Indiana/Marengo', 'America/Indiana/Marengo'), ('America/Indiana/Petersburg', 'America/Indiana/Petersburg'), ('America/Indiana/Tell_City', 'America/Indiana/Tell_City'), ('America/Indiana/Vevay', 'America/Indiana/Vevay'), ('America/Indiana/Vincennes', 'America/Indiana/Vincennes'), ('America/Indiana/Winamac', 'America/Indiana/Winamac'), ('America/Inuvik', 'America/Inuvik'), ('America/Iqaluit', 'America/Iqaluit'), ('America/Jamaica', 'America/Jamaica'), ('America/Juneau', 'America/Juneau'), ('America/Kentucky/Louisville', 'America/Kentucky/Louisville'), ('America/Kentucky/Monticello', 'America/Kentucky/Monticello'), ('America/Kralendijk', 'America/Kralendijk'), ('America/La_Paz', 'America/La_Paz'), ('America/Lima', 'America/Lima'), ('America/Los_Angeles', 'America/Los_Angeles'), ('America/Lower_Princes', 'America/Lower_Princes'), ('America/Maceio', 'America/Maceio'), ('America/Managua', 'America/Managua'), ('America/Manaus', 'America/Manaus'), ('America/Marigot', 'America/Marigot'), ('America/Martinique', 'America/Martinique'), ('America/Matamoros', 'America/Matamoros'), ('America/Mazatlan', 'America/Mazatlan'), ('America/Menominee', 'America/Menominee'), ('America/Merida', 'America/Merida'), ('America/Metlakatla', 'America/Metlakatla'), ('America/Mexico_City', 'America/Mexico_City'), ('America/Miquelon', 'America/Miquelon'), ('America/Moncton', 'America/Moncton'), ('America/Monterrey', 'America/Monterrey'), ('America/Montevideo', 'America/Montevideo'), ('America/Montserrat', 'America/Montserrat'), ('America/Nassau', 'America/Nassau'), ('America/New_York', 'America/New_York'), ('America/Nipigon', 'America/Nipigon'), ('America/Nome', 'America/Nome'), ('America/Noronha', 'America/Noronha'), ('America/North_Dakota/Beulah', 'America/North_Dakota/Beulah'), ('America/North_Dakota/Center', 'America/North_Dakota/Center'), ('America/North_Dakota/New_Salem', 'America/North_Dakota/New_Salem'), ('America/Ojinaga', 'America/Ojinaga'), ('America/Panama', 'America/Panama'), ('America/Pangnirtung', 'America/Pangnirtung'), ('America/Paramaribo', 'America/Paramaribo'), ('America/Phoenix', 'America/Phoenix'), ('America/Port-au-Prince', 'America/Port-au-Prince'), ('America/Port_of_Spain', 'America/Port_of_Spain'), ('America/Porto_Velho', 'America/Porto_Velho'), ('America/Puerto_Rico', 'America/Puerto_Rico'), ('America/Punta_Arenas', 'America/Punta_Arenas'), ('America/Rainy_River', 'America/Rainy_River'), ('America/Rankin_Inlet', 'America/Rankin_Inlet'), ('America/Recife', 'America/Recife'), ('America/Regina', 'America/Regina'), ('America/Resolute', 'America/Resolute'), ('America/Rio_Branco', 'America/Rio_Branco'), ('America/Santarem', 'America/Santarem'), ('America/Santiago', 'America/Santiago'), ('America/Santo_Domingo', 'America/Santo_Domingo'), ('America/Sao_Paulo', 'America/Sao_Paulo'), ('America/Scoresbysund', 'America/Scoresbysund'), ('America/Sitka', 'America/Sitka'), ('America/St_Barthelemy', 'America/St_Barthelemy'), ('America/St_Johns', 'America/St_Johns'), ('America/St_Kitts', 'America/St_Kitts'), ('America/St_Lucia', 'America/St_Lucia'), ('America/St_Thomas', 'America/St_Thomas'), ('America/St_Vincent', 'America/St_Vincent'), ('America/Swift_Current', 'America/Swift_Current'), ('America/Tegucigalpa', 'America/Tegucigalpa'), ('America/Thule', 'America/Thule'), ('America/Thunder_Bay', 'America/Thunder_Bay'), ('America/Tijuana', 'America/Tijuana'), ('America/Toronto', 'America/Toronto'), ('America/Tortola', 'America/Tortola'), ('America/Vancouver', 'America/Vancouver'), ('America/Whitehorse', 'America/Whitehorse'), ('America/Winnipeg', 'America/Winnipeg'), ('America/Yakutat', 'America/Yakutat'), ('America/Yellowknife', 'America/Yellowknife'), ('Antarctica/Casey', 'Antarctica/Casey'), ('Antarctica/Davis', 'Antarctica/Davis'), ('Antarctica/DumontDUrville', 'Antarctica/DumontDUrville'), ('Antarctica/Macquarie', 'Antarctica/Macquarie'), ('Antarctica/Mawson', 'Antarctica/Mawson'), ('Antarctica/McMurdo', 'Antarctica/McMurdo'), ('Antarctica/Palmer', 'Antarctica/Palmer'), ('Antarctica/Rothera', 'Antarctica/Rothera'), ('Antarctica/Syowa', 'Antarctica/Syowa'), ('Antarctica/Troll', 'Antarctica/Troll'), ('Antarctica/Vostok', 'Antarctica/Vostok'), ('Arctic/Longyearbyen', 'Arctic/Longyearbyen'), ('Asia/Aden', 'Asia/Aden'), ('Asia/Almaty', 'Asia/Almaty'), ('Asia/Amman', 'Asia/Amman'), ('Asia/Anadyr', 'Asia/Anadyr'), ('Asia/Aqtau', 'Asia/Aqtau'), ('Asia/Aqtobe', 'Asia/Aqtobe'), ('Asia/Ashgabat', 'Asia/Ashgabat'), ('Asia/Atyrau', 'Asia/Atyrau'), ('Asia/Baghdad', 'Asia/Baghdad'), ('Asia/Bahrain', 'Asia/Bahrain'), ('Asia/Baku', 'Asia/Baku'), ('Asia/Bangkok', 'Asia/Bangkok'), ('Asia/Barnaul', 'Asia/Barnaul'), ('Asia/Beirut', 'Asia/Beirut'), ('Asia/Bishkek', 'Asia/Bishkek'), ('Asia/Brunei', 'Asia/Brunei'), ('Asia/Chita', 'Asia/Chita'), ('Asia/Choibalsan', 'Asia/Choibalsan'), ('Asia/Colombo', 'Asia/Colombo'), ('Asia/Damascus', 'Asia/Damascus'), ('Asia/Dhaka', 'Asia/Dhaka'), ('Asia/Dili', 'Asia/Dili'), ('Asia/Dubai', 'Asia/Dubai'), ('Asia/Dushanbe', 'Asia/Dushanbe'), ('Asia/Famagusta', 'Asia/Famagusta'), ('Asia/Gaza', 'Asia/Gaza'), ('Asia/Hebron', 'Asia/Hebron'), ('Asia/Ho_Chi_Minh', 'Asia/Ho_Chi_Minh'), ('Asia/Hong_Kong', 'Asia/Hong_Kong'), ('Asia/Hovd', 'Asia/Hovd'), ('Asia/Irkutsk', 'Asia/Irkutsk'), ('Asia/Jakarta', 'Asia/Jakarta'), ('Asia/Jayapura', 'Asia/Jayapura'), ('Asia/Jerusalem', 'Asia/Jerusalem'), ('Asia/Kabul', 'Asia/Kabul'), ('Asia/Kamchatka', 'Asia/Kamchatka'), ('Asia/Karachi', 'Asia/Karachi'), ('Asia/Kathmandu', 'Asia/Kathmandu'), ('Asia/Khandyga', 'Asia/Khandyga'), ('Asia/Kolkata', 'Asia/Kolkata'), ('Asia/Krasnoyarsk', 'Asia/Krasnoyarsk'), ('Asia/Kuala_Lumpur', 'Asia/Kuala_Lumpur'), ('Asia/Kuching', 'Asia/Kuching'), ('Asia/Kuwait', 'Asia/Kuwait'), ('Asia/Macau', 'Asia/Macau'), ('Asia/Magadan', 'Asia/Magadan'), ('Asia/Makassar', 'Asia/Makassar'), ('Asia/Manila', 'Asia/Manila'), ('Asia/Muscat', 'Asia/Muscat'), ('Asia/Nicosia', 'Asia/Nicosia'), ('Asia/Novokuznetsk', 'Asia/Novokuznetsk'), ('Asia/Novosibirsk', 'Asia/Novosibirsk'), ('Asia/Omsk', 'Asia/Omsk'), ('Asia/Oral', 'Asia/Oral'), ('Asia/Phnom_Penh', 'Asia/Phnom_Penh'), ('Asia/Pontianak', 'Asia/Pontianak'), ('Asia/Pyongyang', 'Asia/Pyongyang'), ('Asia/Qatar', 'Asia/Qatar'), ('Asia/Qyzylorda', 'Asia/Qyzylorda'), ('Asia/Riyadh', 'Asia/Riyadh'), ('Asia/Sakhalin', 'Asia/Sakhalin'), ('Asia/Samarkand', 'Asia/Samarkand'), ('Asia/Seoul', 'Asia/Seoul'), ('Asia/Shanghai', 'Asia/Shanghai'), ('Asia/Singapore', 'Asia/Singapore'), ('Asia/Srednekolymsk', 'Asia/Srednekolymsk'), ('Asia/Taipei', 'Asia/Taipei'), ('Asia/Tashkent', 'Asia/Tashkent'), ('Asia/Tbilisi', 'Asia/Tbilisi'), ('Asia/Tehran', 'Asia/Tehran'), ('Asia/Thimphu', 'Asia/Thimphu'), ('Asia/Tokyo', 'Asia/Tokyo'), ('Asia/Tomsk', 'Asia/Tomsk'), ('Asia/Ulaanbaatar', 'Asia/Ulaanbaatar'), ('Asia/Urumqi', 'Asia/Urumqi'), ('Asia/Ust-Nera', 'Asia/Ust-Nera'), ('Asia/Vientiane', 'Asia/Vientiane'), ('Asia/Vladivostok', 'Asia/Vladivostok'), ('Asia/Yakutsk', 'Asia/Yakutsk'), ('Asia/Yangon', 'Asia/Yangon'), ('Asia/Yekaterinburg', 'Asia/Yekaterinburg'), ('Asia/Yerevan', 'Asia/Yerevan'), ('Atlantic/Azores', 'Atlantic/Azores'), ('Atlantic/Bermuda', 'Atlantic/Bermuda'), ('Atlantic/Canary', 'Atlantic/Canary'), ('Atlantic/Cape_Verde', 'Atlantic/Cape_Verde'), ('Atlantic/Faroe', 'Atlantic/Faroe'), ('Atlantic/Madeira', 'Atlantic/Madeira'), ('Atlantic/Reykjavik', 'Atlantic/Reykjavik'), ('Atlantic/South_Georgia', 'Atlantic/South_Georgia'), ('Atlantic/St_Helena', 'Atlantic/St_Helena'), ('Atlantic/Stanley', 'Atlantic/Stanley'), ('Australia/Adelaide', 'Australia/Adelaide'), ('Australia/Brisbane', 'Australia/Brisbane'), ('Australia/Broken_Hill', 'Australia/Broken_Hill'), ('Australia/Currie', 'Australia/Currie'), ('Australia/Darwin', 'Australia/Darwin'), ('Australia/Eucla', 'Australia/Eucla'), ('Australia/Hobart', 'Australia/Hobart'), ('Australia/Lindeman', 'Australia/Lindeman'), ('Australia/Lord_Howe', 'Australia/Lord_Howe'), ('Australia/Melbourne', 'Australia/Melbourne'), ('Australia/Perth', 'Australia/Perth'), ('Australia/Sydney', 'Australia/Sydney'), ('Canada/Atlantic', 'Canada/Atlantic'), ('Canada/Central', 'Canada/Central'), ('Canada/Eastern', 'Canada/Eastern'), ('Canada/Mountain', 'Canada/Mountain'), ('Canada/Newfoundland', 'Canada/Newfoundland'), ('Canada/Pacific', 'Canada/Pacific'), ('Europe/Amsterdam', 'Europe/Amsterdam'), ('Europe/Andorra', 'Europe/Andorra'), ('Europe/Astrakhan', 'Europe/Astrakhan'), ('Europe/Athens', 'Europe/Athens'), ('Europe/Belgrade', 'Europe/Belgrade'), ('Europe/Berlin', 'Europe/Berlin'), ('Europe/Bratislava', 'Europe/Bratislava'), ('Europe/Brussels', 'Europe/Brussels'), ('Europe/Bucharest', 'Europe/Bucharest'), ('Europe/Budapest', 'Europe/Budapest'), ('Europe/Busingen', 'Europe/Busingen'), ('Europe/Chisinau', 'Europe/Chisinau'), ('Europe/Copenhagen', 'Europe/Copenhagen'), ('Europe/Dublin', 'Europe/Dublin'), ('Europe/Gibraltar', 'Europe/Gibraltar'), ('Europe/Guernsey', 'Europe/Guernsey'), ('Europe/Helsinki', 'Europe/Helsinki'), ('Europe/Isle_of_Man', 'Europe/Isle_of_Man'), ('Europe/Istanbul', 'Europe/Istanbul'), ('Europe/Jersey', 'Europe/Jersey'), ('Europe/Kaliningrad', 'Europe/Kaliningrad'), ('Europe/Kiev', 'Europe/Kiev'), ('Europe/Kirov', 'Europe/Kirov'), ('Europe/Lisbon', 'Europe/Lisbon'), ('Europe/Ljubljana', 'Europe/Ljubljana'), ('Europe/London', 'Europe/London'), ('Europe/Luxembourg', 'Europe/Luxembourg'), ('Europe/Madrid', 'Europe/Madrid'), ('Europe/Malta', 'Europe/Malta'), ('Europe/Mariehamn', 'Europe/Mariehamn'), ('Europe/Minsk', 'Europe/Minsk'), ('Europe/Monaco', 'Europe/Monaco'), ('Europe/Moscow', 'Europe/Moscow'), ('Europe/Oslo', 'Europe/Oslo'), ('Europe/Paris', 'Europe/Paris'), ('Europe/Podgorica', 'Europe/Podgorica'), ('Europe/Prague', 'Europe/Prague'), ('Europe/Riga', 'Europe/Riga'), ('Europe/Rome', 'Europe/Rome'), ('Europe/Samara', 'Europe/Samara'), ('Europe/San_Marino', 'Europe/San_Marino'), ('Europe/Sarajevo', 'Europe/Sarajevo'), ('Europe/Saratov', 'Europe/Saratov'), ('Europe/Simferopol', 'Europe/Simferopol'), ('Europe/Skopje', 'Europe/Skopje'), ('Europe/Sofia', 'Europe/Sofia'), ('Europe/Stockholm', 'Europe/Stockholm'), ('Europe/Tallinn', 'Europe/Tallinn'), ('Europe/Tirane', 'Europe/Tirane'), ('Europe/Ulyanovsk', 'Europe/Ulyanovsk'), ('Europe/Uzhgorod', 'Europe/Uzhgorod'), ('Europe/Vaduz', 'Europe/Vaduz'), ('Europe/Vatican', 'Europe/Vatican'), ('Europe/Vienna', 'Europe/Vienna'), ('Europe/Vilnius', 'Europe/Vilnius'), ('Europe/Volgograd', 'Europe/Volgograd'), ('Europe/Warsaw', 'Europe/Warsaw'), ('Europe/Zagreb', 'Europe/Zagreb'), ('Europe/Zaporozhye', 'Europe/Zaporozhye'), ('Europe/Zurich', 'Europe/Zurich'), ('GMT', 'GMT'), ('Indian/Antananarivo', 'Indian/Antananarivo'), ('Indian/Chagos', 'Indian/Chagos'), ('Indian/Christmas', 'Indian/Christmas'), ('Indian/Cocos', 'Indian/Cocos'), ('Indian/Comoro', 'Indian/Comoro'), ('Indian/Kerguelen', 'Indian/Kerguelen'), ('Indian/Mahe', 'Indian/Mahe'), ('Indian/Maldives', 'Indian/Maldives'), ('Indian/Mauritius', 'Indian/Mauritius'), ('Indian/Mayotte', 'Indian/Mayotte'), ('Indian/Reunion', 'Indian/Reunion'), ('Pacific/Apia', 'Pacific/Apia'), ('Pacific/Auckland', 'Pacific/Auckland'), ('Pacific/Bougainville', 'Pacific/Bougainville'), ('Pacific/Chatham', 'Pacific/Chatham'), ('Pacific/Chuuk', 'Pacific/Chuuk'), ('Pacific/Easter', 'Pacific/Easter'), ('Pacific/Efate', 'Pacific/Efate'), ('Pacific/Enderbury', 'Pacific/Enderbury'), ('Pacific/Fakaofo', 'Pacific/Fakaofo'), ('Pacific/Fiji', 'Pacific/Fiji'), ('Pacific/Funafuti', 'Pacific/Funafuti'), ('Pacific/Galapagos', 'Pacific/Galapagos'), ('Pacific/Gambier', 'Pacific/Gambier'), ('Pacific/Guadalcanal', 'Pacific/Guadalcanal'), ('Pacific/Guam', 'Pacific/Guam'), ('Pacific/Honolulu', 'Pacific/Honolulu'), ('Pacific/Kiritimati', 'Pacific/Kiritimati'), ('Pacific/Kosrae', 'Pacific/Kosrae'), ('Pacific/Kwajalein', 'Pacific/Kwajalein'), ('Pacific/Majuro', 'Pacific/Majuro'), ('Pacific/Marquesas', 'Pacific/Marquesas'), ('Pacific/Midway', 'Pacific/Midway'), ('Pacific/Nauru', 'Pacific/Nauru'), ('Pacific/Niue', 'Pacific/Niue'), ('Pacific/Norfolk', 'Pacific/Norfolk'), ('Pacific/Noumea', 'Pacific/Noumea'), ('Pacific/Pago_Pago', 'Pacific/Pago_Pago'), ('Pacific/Palau', 'Pacific/Palau'), ('Pacific/Pitcairn', 'Pacific/Pitcairn'), ('Pacific/Pohnpei', 'Pacific/Pohnpei'), ('Pacific/Port_Moresby', 'Pacific/Port_Moresby'), ('Pacific/Rarotonga', 'Pacific/Rarotonga'), ('Pacific/Saipan', 'Pacific/Saipan'), ('Pacific/Tahiti', 'Pacific/Tahiti'), ('Pacific/Tarawa', 'Pacific/Tarawa'), ('Pacific/Tongatapu', 'Pacific/Tongatapu'), ('Pacific/Wake', 'Pacific/Wake'), ('Pacific/Wallis', 'Pacific/Wallis'), ('US/Alaska', 'US/Alaska'), ('US/Arizona', 'US/Arizona'), ('US/Central', 'US/Central'), ('US/Eastern', 'US/Eastern'), ('US/Hawaii', 'US/Hawaii'), ('US/Mountain', 'US/Mountain'), ('US/Pacific', 'US/Pacific'), ('UTC', 'UTC')], default='UTC', help_text='Used for developer clock page', max_length=100),
+ field=models.CharField(
+ choices=[
+ ('Africa/Abidjan', 'Africa/Abidjan'),
+ ('Africa/Accra', 'Africa/Accra'),
+ ('Africa/Addis_Ababa', 'Africa/Addis_Ababa'),
+ ('Africa/Algiers', 'Africa/Algiers'),
+ ('Africa/Asmara', 'Africa/Asmara'),
+ ('Africa/Bamako', 'Africa/Bamako'),
+ ('Africa/Bangui', 'Africa/Bangui'),
+ ('Africa/Banjul', 'Africa/Banjul'),
+ ('Africa/Bissau', 'Africa/Bissau'),
+ ('Africa/Blantyre', 'Africa/Blantyre'),
+ ('Africa/Brazzaville', 'Africa/Brazzaville'),
+ ('Africa/Bujumbura', 'Africa/Bujumbura'),
+ ('Africa/Cairo', 'Africa/Cairo'),
+ ('Africa/Casablanca', 'Africa/Casablanca'),
+ ('Africa/Ceuta', 'Africa/Ceuta'),
+ ('Africa/Conakry', 'Africa/Conakry'),
+ ('Africa/Dakar', 'Africa/Dakar'),
+ ('Africa/Dar_es_Salaam', 'Africa/Dar_es_Salaam'),
+ ('Africa/Djibouti', 'Africa/Djibouti'),
+ ('Africa/Douala', 'Africa/Douala'),
+ ('Africa/El_Aaiun', 'Africa/El_Aaiun'),
+ ('Africa/Freetown', 'Africa/Freetown'),
+ ('Africa/Gaborone', 'Africa/Gaborone'),
+ ('Africa/Harare', 'Africa/Harare'),
+ ('Africa/Johannesburg', 'Africa/Johannesburg'),
+ ('Africa/Juba', 'Africa/Juba'),
+ ('Africa/Kampala', 'Africa/Kampala'),
+ ('Africa/Khartoum', 'Africa/Khartoum'),
+ ('Africa/Kigali', 'Africa/Kigali'),
+ ('Africa/Kinshasa', 'Africa/Kinshasa'),
+ ('Africa/Lagos', 'Africa/Lagos'),
+ ('Africa/Libreville', 'Africa/Libreville'),
+ ('Africa/Lome', 'Africa/Lome'),
+ ('Africa/Luanda', 'Africa/Luanda'),
+ ('Africa/Lubumbashi', 'Africa/Lubumbashi'),
+ ('Africa/Lusaka', 'Africa/Lusaka'),
+ ('Africa/Malabo', 'Africa/Malabo'),
+ ('Africa/Maputo', 'Africa/Maputo'),
+ ('Africa/Maseru', 'Africa/Maseru'),
+ ('Africa/Mbabane', 'Africa/Mbabane'),
+ ('Africa/Mogadishu', 'Africa/Mogadishu'),
+ ('Africa/Monrovia', 'Africa/Monrovia'),
+ ('Africa/Nairobi', 'Africa/Nairobi'),
+ ('Africa/Ndjamena', 'Africa/Ndjamena'),
+ ('Africa/Niamey', 'Africa/Niamey'),
+ ('Africa/Nouakchott', 'Africa/Nouakchott'),
+ ('Africa/Ouagadougou', 'Africa/Ouagadougou'),
+ ('Africa/Porto-Novo', 'Africa/Porto-Novo'),
+ ('Africa/Sao_Tome', 'Africa/Sao_Tome'),
+ ('Africa/Tripoli', 'Africa/Tripoli'),
+ ('Africa/Tunis', 'Africa/Tunis'),
+ ('Africa/Windhoek', 'Africa/Windhoek'),
+ ('America/Adak', 'America/Adak'),
+ ('America/Anchorage', 'America/Anchorage'),
+ ('America/Anguilla', 'America/Anguilla'),
+ ('America/Antigua', 'America/Antigua'),
+ ('America/Araguaina', 'America/Araguaina'),
+ ('America/Argentina/Buenos_Aires', 'America/Argentina/Buenos_Aires'),
+ ('America/Argentina/Catamarca', 'America/Argentina/Catamarca'),
+ ('America/Argentina/Cordoba', 'America/Argentina/Cordoba'),
+ ('America/Argentina/Jujuy', 'America/Argentina/Jujuy'),
+ ('America/Argentina/La_Rioja', 'America/Argentina/La_Rioja'),
+ ('America/Argentina/Mendoza', 'America/Argentina/Mendoza'),
+ ('America/Argentina/Rio_Gallegos', 'America/Argentina/Rio_Gallegos'),
+ ('America/Argentina/Salta', 'America/Argentina/Salta'),
+ ('America/Argentina/San_Juan', 'America/Argentina/San_Juan'),
+ ('America/Argentina/San_Luis', 'America/Argentina/San_Luis'),
+ ('America/Argentina/Tucuman', 'America/Argentina/Tucuman'),
+ ('America/Argentina/Ushuaia', 'America/Argentina/Ushuaia'),
+ ('America/Aruba', 'America/Aruba'),
+ ('America/Asuncion', 'America/Asuncion'),
+ ('America/Atikokan', 'America/Atikokan'),
+ ('America/Bahia', 'America/Bahia'),
+ ('America/Bahia_Banderas', 'America/Bahia_Banderas'),
+ ('America/Barbados', 'America/Barbados'),
+ ('America/Belem', 'America/Belem'),
+ ('America/Belize', 'America/Belize'),
+ ('America/Blanc-Sablon', 'America/Blanc-Sablon'),
+ ('America/Boa_Vista', 'America/Boa_Vista'),
+ ('America/Bogota', 'America/Bogota'),
+ ('America/Boise', 'America/Boise'),
+ ('America/Cambridge_Bay', 'America/Cambridge_Bay'),
+ ('America/Campo_Grande', 'America/Campo_Grande'),
+ ('America/Cancun', 'America/Cancun'),
+ ('America/Caracas', 'America/Caracas'),
+ ('America/Cayenne', 'America/Cayenne'),
+ ('America/Cayman', 'America/Cayman'),
+ ('America/Chicago', 'America/Chicago'),
+ ('America/Chihuahua', 'America/Chihuahua'),
+ ('America/Costa_Rica', 'America/Costa_Rica'),
+ ('America/Creston', 'America/Creston'),
+ ('America/Cuiaba', 'America/Cuiaba'),
+ ('America/Curacao', 'America/Curacao'),
+ ('America/Danmarkshavn', 'America/Danmarkshavn'),
+ ('America/Dawson', 'America/Dawson'),
+ ('America/Dawson_Creek', 'America/Dawson_Creek'),
+ ('America/Denver', 'America/Denver'),
+ ('America/Detroit', 'America/Detroit'),
+ ('America/Dominica', 'America/Dominica'),
+ ('America/Edmonton', 'America/Edmonton'),
+ ('America/Eirunepe', 'America/Eirunepe'),
+ ('America/El_Salvador', 'America/El_Salvador'),
+ ('America/Fort_Nelson', 'America/Fort_Nelson'),
+ ('America/Fortaleza', 'America/Fortaleza'),
+ ('America/Glace_Bay', 'America/Glace_Bay'),
+ ('America/Godthab', 'America/Godthab'),
+ ('America/Goose_Bay', 'America/Goose_Bay'),
+ ('America/Grand_Turk', 'America/Grand_Turk'),
+ ('America/Grenada', 'America/Grenada'),
+ ('America/Guadeloupe', 'America/Guadeloupe'),
+ ('America/Guatemala', 'America/Guatemala'),
+ ('America/Guayaquil', 'America/Guayaquil'),
+ ('America/Guyana', 'America/Guyana'),
+ ('America/Halifax', 'America/Halifax'),
+ ('America/Havana', 'America/Havana'),
+ ('America/Hermosillo', 'America/Hermosillo'),
+ ('America/Indiana/Indianapolis', 'America/Indiana/Indianapolis'),
+ ('America/Indiana/Knox', 'America/Indiana/Knox'),
+ ('America/Indiana/Marengo', 'America/Indiana/Marengo'),
+ ('America/Indiana/Petersburg', 'America/Indiana/Petersburg'),
+ ('America/Indiana/Tell_City', 'America/Indiana/Tell_City'),
+ ('America/Indiana/Vevay', 'America/Indiana/Vevay'),
+ ('America/Indiana/Vincennes', 'America/Indiana/Vincennes'),
+ ('America/Indiana/Winamac', 'America/Indiana/Winamac'),
+ ('America/Inuvik', 'America/Inuvik'),
+ ('America/Iqaluit', 'America/Iqaluit'),
+ ('America/Jamaica', 'America/Jamaica'),
+ ('America/Juneau', 'America/Juneau'),
+ ('America/Kentucky/Louisville', 'America/Kentucky/Louisville'),
+ ('America/Kentucky/Monticello', 'America/Kentucky/Monticello'),
+ ('America/Kralendijk', 'America/Kralendijk'),
+ ('America/La_Paz', 'America/La_Paz'),
+ ('America/Lima', 'America/Lima'),
+ ('America/Los_Angeles', 'America/Los_Angeles'),
+ ('America/Lower_Princes', 'America/Lower_Princes'),
+ ('America/Maceio', 'America/Maceio'),
+ ('America/Managua', 'America/Managua'),
+ ('America/Manaus', 'America/Manaus'),
+ ('America/Marigot', 'America/Marigot'),
+ ('America/Martinique', 'America/Martinique'),
+ ('America/Matamoros', 'America/Matamoros'),
+ ('America/Mazatlan', 'America/Mazatlan'),
+ ('America/Menominee', 'America/Menominee'),
+ ('America/Merida', 'America/Merida'),
+ ('America/Metlakatla', 'America/Metlakatla'),
+ ('America/Mexico_City', 'America/Mexico_City'),
+ ('America/Miquelon', 'America/Miquelon'),
+ ('America/Moncton', 'America/Moncton'),
+ ('America/Monterrey', 'America/Monterrey'),
+ ('America/Montevideo', 'America/Montevideo'),
+ ('America/Montserrat', 'America/Montserrat'),
+ ('America/Nassau', 'America/Nassau'),
+ ('America/New_York', 'America/New_York'),
+ ('America/Nipigon', 'America/Nipigon'),
+ ('America/Nome', 'America/Nome'),
+ ('America/Noronha', 'America/Noronha'),
+ ('America/North_Dakota/Beulah', 'America/North_Dakota/Beulah'),
+ ('America/North_Dakota/Center', 'America/North_Dakota/Center'),
+ ('America/North_Dakota/New_Salem', 'America/North_Dakota/New_Salem'),
+ ('America/Ojinaga', 'America/Ojinaga'),
+ ('America/Panama', 'America/Panama'),
+ ('America/Pangnirtung', 'America/Pangnirtung'),
+ ('America/Paramaribo', 'America/Paramaribo'),
+ ('America/Phoenix', 'America/Phoenix'),
+ ('America/Port-au-Prince', 'America/Port-au-Prince'),
+ ('America/Port_of_Spain', 'America/Port_of_Spain'),
+ ('America/Porto_Velho', 'America/Porto_Velho'),
+ ('America/Puerto_Rico', 'America/Puerto_Rico'),
+ ('America/Punta_Arenas', 'America/Punta_Arenas'),
+ ('America/Rainy_River', 'America/Rainy_River'),
+ ('America/Rankin_Inlet', 'America/Rankin_Inlet'),
+ ('America/Recife', 'America/Recife'),
+ ('America/Regina', 'America/Regina'),
+ ('America/Resolute', 'America/Resolute'),
+ ('America/Rio_Branco', 'America/Rio_Branco'),
+ ('America/Santarem', 'America/Santarem'),
+ ('America/Santiago', 'America/Santiago'),
+ ('America/Santo_Domingo', 'America/Santo_Domingo'),
+ ('America/Sao_Paulo', 'America/Sao_Paulo'),
+ ('America/Scoresbysund', 'America/Scoresbysund'),
+ ('America/Sitka', 'America/Sitka'),
+ ('America/St_Barthelemy', 'America/St_Barthelemy'),
+ ('America/St_Johns', 'America/St_Johns'),
+ ('America/St_Kitts', 'America/St_Kitts'),
+ ('America/St_Lucia', 'America/St_Lucia'),
+ ('America/St_Thomas', 'America/St_Thomas'),
+ ('America/St_Vincent', 'America/St_Vincent'),
+ ('America/Swift_Current', 'America/Swift_Current'),
+ ('America/Tegucigalpa', 'America/Tegucigalpa'),
+ ('America/Thule', 'America/Thule'),
+ ('America/Thunder_Bay', 'America/Thunder_Bay'),
+ ('America/Tijuana', 'America/Tijuana'),
+ ('America/Toronto', 'America/Toronto'),
+ ('America/Tortola', 'America/Tortola'),
+ ('America/Vancouver', 'America/Vancouver'),
+ ('America/Whitehorse', 'America/Whitehorse'),
+ ('America/Winnipeg', 'America/Winnipeg'),
+ ('America/Yakutat', 'America/Yakutat'),
+ ('America/Yellowknife', 'America/Yellowknife'),
+ ('Antarctica/Casey', 'Antarctica/Casey'),
+ ('Antarctica/Davis', 'Antarctica/Davis'),
+ ('Antarctica/DumontDUrville', 'Antarctica/DumontDUrville'),
+ ('Antarctica/Macquarie', 'Antarctica/Macquarie'),
+ ('Antarctica/Mawson', 'Antarctica/Mawson'),
+ ('Antarctica/McMurdo', 'Antarctica/McMurdo'),
+ ('Antarctica/Palmer', 'Antarctica/Palmer'),
+ ('Antarctica/Rothera', 'Antarctica/Rothera'),
+ ('Antarctica/Syowa', 'Antarctica/Syowa'),
+ ('Antarctica/Troll', 'Antarctica/Troll'),
+ ('Antarctica/Vostok', 'Antarctica/Vostok'),
+ ('Arctic/Longyearbyen', 'Arctic/Longyearbyen'),
+ ('Asia/Aden', 'Asia/Aden'),
+ ('Asia/Almaty', 'Asia/Almaty'),
+ ('Asia/Amman', 'Asia/Amman'),
+ ('Asia/Anadyr', 'Asia/Anadyr'),
+ ('Asia/Aqtau', 'Asia/Aqtau'),
+ ('Asia/Aqtobe', 'Asia/Aqtobe'),
+ ('Asia/Ashgabat', 'Asia/Ashgabat'),
+ ('Asia/Atyrau', 'Asia/Atyrau'),
+ ('Asia/Baghdad', 'Asia/Baghdad'),
+ ('Asia/Bahrain', 'Asia/Bahrain'),
+ ('Asia/Baku', 'Asia/Baku'),
+ ('Asia/Bangkok', 'Asia/Bangkok'),
+ ('Asia/Barnaul', 'Asia/Barnaul'),
+ ('Asia/Beirut', 'Asia/Beirut'),
+ ('Asia/Bishkek', 'Asia/Bishkek'),
+ ('Asia/Brunei', 'Asia/Brunei'),
+ ('Asia/Chita', 'Asia/Chita'),
+ ('Asia/Choibalsan', 'Asia/Choibalsan'),
+ ('Asia/Colombo', 'Asia/Colombo'),
+ ('Asia/Damascus', 'Asia/Damascus'),
+ ('Asia/Dhaka', 'Asia/Dhaka'),
+ ('Asia/Dili', 'Asia/Dili'),
+ ('Asia/Dubai', 'Asia/Dubai'),
+ ('Asia/Dushanbe', 'Asia/Dushanbe'),
+ ('Asia/Famagusta', 'Asia/Famagusta'),
+ ('Asia/Gaza', 'Asia/Gaza'),
+ ('Asia/Hebron', 'Asia/Hebron'),
+ ('Asia/Ho_Chi_Minh', 'Asia/Ho_Chi_Minh'),
+ ('Asia/Hong_Kong', 'Asia/Hong_Kong'),
+ ('Asia/Hovd', 'Asia/Hovd'),
+ ('Asia/Irkutsk', 'Asia/Irkutsk'),
+ ('Asia/Jakarta', 'Asia/Jakarta'),
+ ('Asia/Jayapura', 'Asia/Jayapura'),
+ ('Asia/Jerusalem', 'Asia/Jerusalem'),
+ ('Asia/Kabul', 'Asia/Kabul'),
+ ('Asia/Kamchatka', 'Asia/Kamchatka'),
+ ('Asia/Karachi', 'Asia/Karachi'),
+ ('Asia/Kathmandu', 'Asia/Kathmandu'),
+ ('Asia/Khandyga', 'Asia/Khandyga'),
+ ('Asia/Kolkata', 'Asia/Kolkata'),
+ ('Asia/Krasnoyarsk', 'Asia/Krasnoyarsk'),
+ ('Asia/Kuala_Lumpur', 'Asia/Kuala_Lumpur'),
+ ('Asia/Kuching', 'Asia/Kuching'),
+ ('Asia/Kuwait', 'Asia/Kuwait'),
+ ('Asia/Macau', 'Asia/Macau'),
+ ('Asia/Magadan', 'Asia/Magadan'),
+ ('Asia/Makassar', 'Asia/Makassar'),
+ ('Asia/Manila', 'Asia/Manila'),
+ ('Asia/Muscat', 'Asia/Muscat'),
+ ('Asia/Nicosia', 'Asia/Nicosia'),
+ ('Asia/Novokuznetsk', 'Asia/Novokuznetsk'),
+ ('Asia/Novosibirsk', 'Asia/Novosibirsk'),
+ ('Asia/Omsk', 'Asia/Omsk'),
+ ('Asia/Oral', 'Asia/Oral'),
+ ('Asia/Phnom_Penh', 'Asia/Phnom_Penh'),
+ ('Asia/Pontianak', 'Asia/Pontianak'),
+ ('Asia/Pyongyang', 'Asia/Pyongyang'),
+ ('Asia/Qatar', 'Asia/Qatar'),
+ ('Asia/Qyzylorda', 'Asia/Qyzylorda'),
+ ('Asia/Riyadh', 'Asia/Riyadh'),
+ ('Asia/Sakhalin', 'Asia/Sakhalin'),
+ ('Asia/Samarkand', 'Asia/Samarkand'),
+ ('Asia/Seoul', 'Asia/Seoul'),
+ ('Asia/Shanghai', 'Asia/Shanghai'),
+ ('Asia/Singapore', 'Asia/Singapore'),
+ ('Asia/Srednekolymsk', 'Asia/Srednekolymsk'),
+ ('Asia/Taipei', 'Asia/Taipei'),
+ ('Asia/Tashkent', 'Asia/Tashkent'),
+ ('Asia/Tbilisi', 'Asia/Tbilisi'),
+ ('Asia/Tehran', 'Asia/Tehran'),
+ ('Asia/Thimphu', 'Asia/Thimphu'),
+ ('Asia/Tokyo', 'Asia/Tokyo'),
+ ('Asia/Tomsk', 'Asia/Tomsk'),
+ ('Asia/Ulaanbaatar', 'Asia/Ulaanbaatar'),
+ ('Asia/Urumqi', 'Asia/Urumqi'),
+ ('Asia/Ust-Nera', 'Asia/Ust-Nera'),
+ ('Asia/Vientiane', 'Asia/Vientiane'),
+ ('Asia/Vladivostok', 'Asia/Vladivostok'),
+ ('Asia/Yakutsk', 'Asia/Yakutsk'),
+ ('Asia/Yangon', 'Asia/Yangon'),
+ ('Asia/Yekaterinburg', 'Asia/Yekaterinburg'),
+ ('Asia/Yerevan', 'Asia/Yerevan'),
+ ('Atlantic/Azores', 'Atlantic/Azores'),
+ ('Atlantic/Bermuda', 'Atlantic/Bermuda'),
+ ('Atlantic/Canary', 'Atlantic/Canary'),
+ ('Atlantic/Cape_Verde', 'Atlantic/Cape_Verde'),
+ ('Atlantic/Faroe', 'Atlantic/Faroe'),
+ ('Atlantic/Madeira', 'Atlantic/Madeira'),
+ ('Atlantic/Reykjavik', 'Atlantic/Reykjavik'),
+ ('Atlantic/South_Georgia', 'Atlantic/South_Georgia'),
+ ('Atlantic/St_Helena', 'Atlantic/St_Helena'),
+ ('Atlantic/Stanley', 'Atlantic/Stanley'),
+ ('Australia/Adelaide', 'Australia/Adelaide'),
+ ('Australia/Brisbane', 'Australia/Brisbane'),
+ ('Australia/Broken_Hill', 'Australia/Broken_Hill'),
+ ('Australia/Currie', 'Australia/Currie'),
+ ('Australia/Darwin', 'Australia/Darwin'),
+ ('Australia/Eucla', 'Australia/Eucla'),
+ ('Australia/Hobart', 'Australia/Hobart'),
+ ('Australia/Lindeman', 'Australia/Lindeman'),
+ ('Australia/Lord_Howe', 'Australia/Lord_Howe'),
+ ('Australia/Melbourne', 'Australia/Melbourne'),
+ ('Australia/Perth', 'Australia/Perth'),
+ ('Australia/Sydney', 'Australia/Sydney'),
+ ('Canada/Atlantic', 'Canada/Atlantic'),
+ ('Canada/Central', 'Canada/Central'),
+ ('Canada/Eastern', 'Canada/Eastern'),
+ ('Canada/Mountain', 'Canada/Mountain'),
+ ('Canada/Newfoundland', 'Canada/Newfoundland'),
+ ('Canada/Pacific', 'Canada/Pacific'),
+ ('Europe/Amsterdam', 'Europe/Amsterdam'),
+ ('Europe/Andorra', 'Europe/Andorra'),
+ ('Europe/Astrakhan', 'Europe/Astrakhan'),
+ ('Europe/Athens', 'Europe/Athens'),
+ ('Europe/Belgrade', 'Europe/Belgrade'),
+ ('Europe/Berlin', 'Europe/Berlin'),
+ ('Europe/Bratislava', 'Europe/Bratislava'),
+ ('Europe/Brussels', 'Europe/Brussels'),
+ ('Europe/Bucharest', 'Europe/Bucharest'),
+ ('Europe/Budapest', 'Europe/Budapest'),
+ ('Europe/Busingen', 'Europe/Busingen'),
+ ('Europe/Chisinau', 'Europe/Chisinau'),
+ ('Europe/Copenhagen', 'Europe/Copenhagen'),
+ ('Europe/Dublin', 'Europe/Dublin'),
+ ('Europe/Gibraltar', 'Europe/Gibraltar'),
+ ('Europe/Guernsey', 'Europe/Guernsey'),
+ ('Europe/Helsinki', 'Europe/Helsinki'),
+ ('Europe/Isle_of_Man', 'Europe/Isle_of_Man'),
+ ('Europe/Istanbul', 'Europe/Istanbul'),
+ ('Europe/Jersey', 'Europe/Jersey'),
+ ('Europe/Kaliningrad', 'Europe/Kaliningrad'),
+ ('Europe/Kiev', 'Europe/Kiev'),
+ ('Europe/Kirov', 'Europe/Kirov'),
+ ('Europe/Lisbon', 'Europe/Lisbon'),
+ ('Europe/Ljubljana', 'Europe/Ljubljana'),
+ ('Europe/London', 'Europe/London'),
+ ('Europe/Luxembourg', 'Europe/Luxembourg'),
+ ('Europe/Madrid', 'Europe/Madrid'),
+ ('Europe/Malta', 'Europe/Malta'),
+ ('Europe/Mariehamn', 'Europe/Mariehamn'),
+ ('Europe/Minsk', 'Europe/Minsk'),
+ ('Europe/Monaco', 'Europe/Monaco'),
+ ('Europe/Moscow', 'Europe/Moscow'),
+ ('Europe/Oslo', 'Europe/Oslo'),
+ ('Europe/Paris', 'Europe/Paris'),
+ ('Europe/Podgorica', 'Europe/Podgorica'),
+ ('Europe/Prague', 'Europe/Prague'),
+ ('Europe/Riga', 'Europe/Riga'),
+ ('Europe/Rome', 'Europe/Rome'),
+ ('Europe/Samara', 'Europe/Samara'),
+ ('Europe/San_Marino', 'Europe/San_Marino'),
+ ('Europe/Sarajevo', 'Europe/Sarajevo'),
+ ('Europe/Saratov', 'Europe/Saratov'),
+ ('Europe/Simferopol', 'Europe/Simferopol'),
+ ('Europe/Skopje', 'Europe/Skopje'),
+ ('Europe/Sofia', 'Europe/Sofia'),
+ ('Europe/Stockholm', 'Europe/Stockholm'),
+ ('Europe/Tallinn', 'Europe/Tallinn'),
+ ('Europe/Tirane', 'Europe/Tirane'),
+ ('Europe/Ulyanovsk', 'Europe/Ulyanovsk'),
+ ('Europe/Uzhgorod', 'Europe/Uzhgorod'),
+ ('Europe/Vaduz', 'Europe/Vaduz'),
+ ('Europe/Vatican', 'Europe/Vatican'),
+ ('Europe/Vienna', 'Europe/Vienna'),
+ ('Europe/Vilnius', 'Europe/Vilnius'),
+ ('Europe/Volgograd', 'Europe/Volgograd'),
+ ('Europe/Warsaw', 'Europe/Warsaw'),
+ ('Europe/Zagreb', 'Europe/Zagreb'),
+ ('Europe/Zaporozhye', 'Europe/Zaporozhye'),
+ ('Europe/Zurich', 'Europe/Zurich'),
+ ('GMT', 'GMT'),
+ ('Indian/Antananarivo', 'Indian/Antananarivo'),
+ ('Indian/Chagos', 'Indian/Chagos'),
+ ('Indian/Christmas', 'Indian/Christmas'),
+ ('Indian/Cocos', 'Indian/Cocos'),
+ ('Indian/Comoro', 'Indian/Comoro'),
+ ('Indian/Kerguelen', 'Indian/Kerguelen'),
+ ('Indian/Mahe', 'Indian/Mahe'),
+ ('Indian/Maldives', 'Indian/Maldives'),
+ ('Indian/Mauritius', 'Indian/Mauritius'),
+ ('Indian/Mayotte', 'Indian/Mayotte'),
+ ('Indian/Reunion', 'Indian/Reunion'),
+ ('Pacific/Apia', 'Pacific/Apia'),
+ ('Pacific/Auckland', 'Pacific/Auckland'),
+ ('Pacific/Bougainville', 'Pacific/Bougainville'),
+ ('Pacific/Chatham', 'Pacific/Chatham'),
+ ('Pacific/Chuuk', 'Pacific/Chuuk'),
+ ('Pacific/Easter', 'Pacific/Easter'),
+ ('Pacific/Efate', 'Pacific/Efate'),
+ ('Pacific/Enderbury', 'Pacific/Enderbury'),
+ ('Pacific/Fakaofo', 'Pacific/Fakaofo'),
+ ('Pacific/Fiji', 'Pacific/Fiji'),
+ ('Pacific/Funafuti', 'Pacific/Funafuti'),
+ ('Pacific/Galapagos', 'Pacific/Galapagos'),
+ ('Pacific/Gambier', 'Pacific/Gambier'),
+ ('Pacific/Guadalcanal', 'Pacific/Guadalcanal'),
+ ('Pacific/Guam', 'Pacific/Guam'),
+ ('Pacific/Honolulu', 'Pacific/Honolulu'),
+ ('Pacific/Kiritimati', 'Pacific/Kiritimati'),
+ ('Pacific/Kosrae', 'Pacific/Kosrae'),
+ ('Pacific/Kwajalein', 'Pacific/Kwajalein'),
+ ('Pacific/Majuro', 'Pacific/Majuro'),
+ ('Pacific/Marquesas', 'Pacific/Marquesas'),
+ ('Pacific/Midway', 'Pacific/Midway'),
+ ('Pacific/Nauru', 'Pacific/Nauru'),
+ ('Pacific/Niue', 'Pacific/Niue'),
+ ('Pacific/Norfolk', 'Pacific/Norfolk'),
+ ('Pacific/Noumea', 'Pacific/Noumea'),
+ ('Pacific/Pago_Pago', 'Pacific/Pago_Pago'),
+ ('Pacific/Palau', 'Pacific/Palau'),
+ ('Pacific/Pitcairn', 'Pacific/Pitcairn'),
+ ('Pacific/Pohnpei', 'Pacific/Pohnpei'),
+ ('Pacific/Port_Moresby', 'Pacific/Port_Moresby'),
+ ('Pacific/Rarotonga', 'Pacific/Rarotonga'),
+ ('Pacific/Saipan', 'Pacific/Saipan'),
+ ('Pacific/Tahiti', 'Pacific/Tahiti'),
+ ('Pacific/Tarawa', 'Pacific/Tarawa'),
+ ('Pacific/Tongatapu', 'Pacific/Tongatapu'),
+ ('Pacific/Wake', 'Pacific/Wake'),
+ ('Pacific/Wallis', 'Pacific/Wallis'),
+ ('US/Alaska', 'US/Alaska'),
+ ('US/Arizona', 'US/Arizona'),
+ ('US/Central', 'US/Central'),
+ ('US/Eastern', 'US/Eastern'),
+ ('US/Hawaii', 'US/Hawaii'),
+ ('US/Mountain', 'US/Mountain'),
+ ('US/Pacific', 'US/Pacific'),
+ ('UTC', 'UTC')],
+ default='UTC', help_text='Used for developer clock page', max_length=100),
),
]
diff --git a/devel/migrations/0003_auto_20191009_1924.py b/devel/migrations/0003_auto_20191009_1924.py
index e292a877..2581dacd 100644
--- a/devel/migrations/0003_auto_20191009_1924.py
+++ b/devel/migrations/0003_auto_20191009_1924.py
@@ -13,6 +13,448 @@ class Migration(migrations.Migration):
migrations.AlterField(
model_name='userprofile',
name='time_zone',
- field=models.CharField(choices=[('Africa/Abidjan', 'Africa/Abidjan'), ('Africa/Accra', 'Africa/Accra'), ('Africa/Addis_Ababa', 'Africa/Addis_Ababa'), ('Africa/Algiers', 'Africa/Algiers'), ('Africa/Asmara', 'Africa/Asmara'), ('Africa/Bamako', 'Africa/Bamako'), ('Africa/Bangui', 'Africa/Bangui'), ('Africa/Banjul', 'Africa/Banjul'), ('Africa/Bissau', 'Africa/Bissau'), ('Africa/Blantyre', 'Africa/Blantyre'), ('Africa/Brazzaville', 'Africa/Brazzaville'), ('Africa/Bujumbura', 'Africa/Bujumbura'), ('Africa/Cairo', 'Africa/Cairo'), ('Africa/Casablanca', 'Africa/Casablanca'), ('Africa/Ceuta', 'Africa/Ceuta'), ('Africa/Conakry', 'Africa/Conakry'), ('Africa/Dakar', 'Africa/Dakar'), ('Africa/Dar_es_Salaam', 'Africa/Dar_es_Salaam'), ('Africa/Djibouti', 'Africa/Djibouti'), ('Africa/Douala', 'Africa/Douala'), ('Africa/El_Aaiun', 'Africa/El_Aaiun'), ('Africa/Freetown', 'Africa/Freetown'), ('Africa/Gaborone', 'Africa/Gaborone'), ('Africa/Harare', 'Africa/Harare'), ('Africa/Johannesburg', 'Africa/Johannesburg'), ('Africa/Juba', 'Africa/Juba'), ('Africa/Kampala', 'Africa/Kampala'), ('Africa/Khartoum', 'Africa/Khartoum'), ('Africa/Kigali', 'Africa/Kigali'), ('Africa/Kinshasa', 'Africa/Kinshasa'), ('Africa/Lagos', 'Africa/Lagos'), ('Africa/Libreville', 'Africa/Libreville'), ('Africa/Lome', 'Africa/Lome'), ('Africa/Luanda', 'Africa/Luanda'), ('Africa/Lubumbashi', 'Africa/Lubumbashi'), ('Africa/Lusaka', 'Africa/Lusaka'), ('Africa/Malabo', 'Africa/Malabo'), ('Africa/Maputo', 'Africa/Maputo'), ('Africa/Maseru', 'Africa/Maseru'), ('Africa/Mbabane', 'Africa/Mbabane'), ('Africa/Mogadishu', 'Africa/Mogadishu'), ('Africa/Monrovia', 'Africa/Monrovia'), ('Africa/Nairobi', 'Africa/Nairobi'), ('Africa/Ndjamena', 'Africa/Ndjamena'), ('Africa/Niamey', 'Africa/Niamey'), ('Africa/Nouakchott', 'Africa/Nouakchott'), ('Africa/Ouagadougou', 'Africa/Ouagadougou'), ('Africa/Porto-Novo', 'Africa/Porto-Novo'), ('Africa/Sao_Tome', 'Africa/Sao_Tome'), ('Africa/Tripoli', 'Africa/Tripoli'), ('Africa/Tunis', 'Africa/Tunis'), ('Africa/Windhoek', 'Africa/Windhoek'), ('America/Adak', 'America/Adak'), ('America/Anchorage', 'America/Anchorage'), ('America/Anguilla', 'America/Anguilla'), ('America/Antigua', 'America/Antigua'), ('America/Araguaina', 'America/Araguaina'), ('America/Argentina/Buenos_Aires', 'America/Argentina/Buenos_Aires'), ('America/Argentina/Catamarca', 'America/Argentina/Catamarca'), ('America/Argentina/Cordoba', 'America/Argentina/Cordoba'), ('America/Argentina/Jujuy', 'America/Argentina/Jujuy'), ('America/Argentina/La_Rioja', 'America/Argentina/La_Rioja'), ('America/Argentina/Mendoza', 'America/Argentina/Mendoza'), ('America/Argentina/Rio_Gallegos', 'America/Argentina/Rio_Gallegos'), ('America/Argentina/Salta', 'America/Argentina/Salta'), ('America/Argentina/San_Juan', 'America/Argentina/San_Juan'), ('America/Argentina/San_Luis', 'America/Argentina/San_Luis'), ('America/Argentina/Tucuman', 'America/Argentina/Tucuman'), ('America/Argentina/Ushuaia', 'America/Argentina/Ushuaia'), ('America/Aruba', 'America/Aruba'), ('America/Asuncion', 'America/Asuncion'), ('America/Atikokan', 'America/Atikokan'), ('America/Bahia', 'America/Bahia'), ('America/Bahia_Banderas', 'America/Bahia_Banderas'), ('America/Barbados', 'America/Barbados'), ('America/Belem', 'America/Belem'), ('America/Belize', 'America/Belize'), ('America/Blanc-Sablon', 'America/Blanc-Sablon'), ('America/Boa_Vista', 'America/Boa_Vista'), ('America/Bogota', 'America/Bogota'), ('America/Boise', 'America/Boise'), ('America/Cambridge_Bay', 'America/Cambridge_Bay'), ('America/Campo_Grande', 'America/Campo_Grande'), ('America/Cancun', 'America/Cancun'), ('America/Caracas', 'America/Caracas'), ('America/Cayenne', 'America/Cayenne'), ('America/Cayman', 'America/Cayman'), ('America/Chicago', 'America/Chicago'), ('America/Chihuahua', 'America/Chihuahua'), ('America/Costa_Rica', 'America/Costa_Rica'), ('America/Creston', 'America/Creston'), ('America/Cuiaba', 'America/Cuiaba'), ('America/Curacao', 'America/Curacao'), ('America/Danmarkshavn', 'America/Danmarkshavn'), ('America/Dawson', 'America/Dawson'), ('America/Dawson_Creek', 'America/Dawson_Creek'), ('America/Denver', 'America/Denver'), ('America/Detroit', 'America/Detroit'), ('America/Dominica', 'America/Dominica'), ('America/Edmonton', 'America/Edmonton'), ('America/Eirunepe', 'America/Eirunepe'), ('America/El_Salvador', 'America/El_Salvador'), ('America/Fort_Nelson', 'America/Fort_Nelson'), ('America/Fortaleza', 'America/Fortaleza'), ('America/Glace_Bay', 'America/Glace_Bay'), ('America/Godthab', 'America/Godthab'), ('America/Goose_Bay', 'America/Goose_Bay'), ('America/Grand_Turk', 'America/Grand_Turk'), ('America/Grenada', 'America/Grenada'), ('America/Guadeloupe', 'America/Guadeloupe'), ('America/Guatemala', 'America/Guatemala'), ('America/Guayaquil', 'America/Guayaquil'), ('America/Guyana', 'America/Guyana'), ('America/Halifax', 'America/Halifax'), ('America/Havana', 'America/Havana'), ('America/Hermosillo', 'America/Hermosillo'), ('America/Indiana/Indianapolis', 'America/Indiana/Indianapolis'), ('America/Indiana/Knox', 'America/Indiana/Knox'), ('America/Indiana/Marengo', 'America/Indiana/Marengo'), ('America/Indiana/Petersburg', 'America/Indiana/Petersburg'), ('America/Indiana/Tell_City', 'America/Indiana/Tell_City'), ('America/Indiana/Vevay', 'America/Indiana/Vevay'), ('America/Indiana/Vincennes', 'America/Indiana/Vincennes'), ('America/Indiana/Winamac', 'America/Indiana/Winamac'), ('America/Inuvik', 'America/Inuvik'), ('America/Iqaluit', 'America/Iqaluit'), ('America/Jamaica', 'America/Jamaica'), ('America/Juneau', 'America/Juneau'), ('America/Kentucky/Louisville', 'America/Kentucky/Louisville'), ('America/Kentucky/Monticello', 'America/Kentucky/Monticello'), ('America/Kralendijk', 'America/Kralendijk'), ('America/La_Paz', 'America/La_Paz'), ('America/Lima', 'America/Lima'), ('America/Los_Angeles', 'America/Los_Angeles'), ('America/Lower_Princes', 'America/Lower_Princes'), ('America/Maceio', 'America/Maceio'), ('America/Managua', 'America/Managua'), ('America/Manaus', 'America/Manaus'), ('America/Marigot', 'America/Marigot'), ('America/Martinique', 'America/Martinique'), ('America/Matamoros', 'America/Matamoros'), ('America/Mazatlan', 'America/Mazatlan'), ('America/Menominee', 'America/Menominee'), ('America/Merida', 'America/Merida'), ('America/Metlakatla', 'America/Metlakatla'), ('America/Mexico_City', 'America/Mexico_City'), ('America/Miquelon', 'America/Miquelon'), ('America/Moncton', 'America/Moncton'), ('America/Monterrey', 'America/Monterrey'), ('America/Montevideo', 'America/Montevideo'), ('America/Montserrat', 'America/Montserrat'), ('America/Nassau', 'America/Nassau'), ('America/New_York', 'America/New_York'), ('America/Nipigon', 'America/Nipigon'), ('America/Nome', 'America/Nome'), ('America/Noronha', 'America/Noronha'), ('America/North_Dakota/Beulah', 'America/North_Dakota/Beulah'), ('America/North_Dakota/Center', 'America/North_Dakota/Center'), ('America/North_Dakota/New_Salem', 'America/North_Dakota/New_Salem'), ('America/Ojinaga', 'America/Ojinaga'), ('America/Panama', 'America/Panama'), ('America/Pangnirtung', 'America/Pangnirtung'), ('America/Paramaribo', 'America/Paramaribo'), ('America/Phoenix', 'America/Phoenix'), ('America/Port-au-Prince', 'America/Port-au-Prince'), ('America/Port_of_Spain', 'America/Port_of_Spain'), ('America/Porto_Velho', 'America/Porto_Velho'), ('America/Puerto_Rico', 'America/Puerto_Rico'), ('America/Punta_Arenas', 'America/Punta_Arenas'), ('America/Rainy_River', 'America/Rainy_River'), ('America/Rankin_Inlet', 'America/Rankin_Inlet'), ('America/Recife', 'America/Recife'), ('America/Regina', 'America/Regina'), ('America/Resolute', 'America/Resolute'), ('America/Rio_Branco', 'America/Rio_Branco'), ('America/Santarem', 'America/Santarem'), ('America/Santiago', 'America/Santiago'), ('America/Santo_Domingo', 'America/Santo_Domingo'), ('America/Sao_Paulo', 'America/Sao_Paulo'), ('America/Scoresbysund', 'America/Scoresbysund'), ('America/Sitka', 'America/Sitka'), ('America/St_Barthelemy', 'America/St_Barthelemy'), ('America/St_Johns', 'America/St_Johns'), ('America/St_Kitts', 'America/St_Kitts'), ('America/St_Lucia', 'America/St_Lucia'), ('America/St_Thomas', 'America/St_Thomas'), ('America/St_Vincent', 'America/St_Vincent'), ('America/Swift_Current', 'America/Swift_Current'), ('America/Tegucigalpa', 'America/Tegucigalpa'), ('America/Thule', 'America/Thule'), ('America/Thunder_Bay', 'America/Thunder_Bay'), ('America/Tijuana', 'America/Tijuana'), ('America/Toronto', 'America/Toronto'), ('America/Tortola', 'America/Tortola'), ('America/Vancouver', 'America/Vancouver'), ('America/Whitehorse', 'America/Whitehorse'), ('America/Winnipeg', 'America/Winnipeg'), ('America/Yakutat', 'America/Yakutat'), ('America/Yellowknife', 'America/Yellowknife'), ('Antarctica/Casey', 'Antarctica/Casey'), ('Antarctica/Davis', 'Antarctica/Davis'), ('Antarctica/DumontDUrville', 'Antarctica/DumontDUrville'), ('Antarctica/Macquarie', 'Antarctica/Macquarie'), ('Antarctica/Mawson', 'Antarctica/Mawson'), ('Antarctica/McMurdo', 'Antarctica/McMurdo'), ('Antarctica/Palmer', 'Antarctica/Palmer'), ('Antarctica/Rothera', 'Antarctica/Rothera'), ('Antarctica/Syowa', 'Antarctica/Syowa'), ('Antarctica/Troll', 'Antarctica/Troll'), ('Antarctica/Vostok', 'Antarctica/Vostok'), ('Arctic/Longyearbyen', 'Arctic/Longyearbyen'), ('Asia/Aden', 'Asia/Aden'), ('Asia/Almaty', 'Asia/Almaty'), ('Asia/Amman', 'Asia/Amman'), ('Asia/Anadyr', 'Asia/Anadyr'), ('Asia/Aqtau', 'Asia/Aqtau'), ('Asia/Aqtobe', 'Asia/Aqtobe'), ('Asia/Ashgabat', 'Asia/Ashgabat'), ('Asia/Atyrau', 'Asia/Atyrau'), ('Asia/Baghdad', 'Asia/Baghdad'), ('Asia/Bahrain', 'Asia/Bahrain'), ('Asia/Baku', 'Asia/Baku'), ('Asia/Bangkok', 'Asia/Bangkok'), ('Asia/Barnaul', 'Asia/Barnaul'), ('Asia/Beirut', 'Asia/Beirut'), ('Asia/Bishkek', 'Asia/Bishkek'), ('Asia/Brunei', 'Asia/Brunei'), ('Asia/Chita', 'Asia/Chita'), ('Asia/Choibalsan', 'Asia/Choibalsan'), ('Asia/Colombo', 'Asia/Colombo'), ('Asia/Damascus', 'Asia/Damascus'), ('Asia/Dhaka', 'Asia/Dhaka'), ('Asia/Dili', 'Asia/Dili'), ('Asia/Dubai', 'Asia/Dubai'), ('Asia/Dushanbe', 'Asia/Dushanbe'), ('Asia/Famagusta', 'Asia/Famagusta'), ('Asia/Gaza', 'Asia/Gaza'), ('Asia/Hebron', 'Asia/Hebron'), ('Asia/Ho_Chi_Minh', 'Asia/Ho_Chi_Minh'), ('Asia/Hong_Kong', 'Asia/Hong_Kong'), ('Asia/Hovd', 'Asia/Hovd'), ('Asia/Irkutsk', 'Asia/Irkutsk'), ('Asia/Jakarta', 'Asia/Jakarta'), ('Asia/Jayapura', 'Asia/Jayapura'), ('Asia/Jerusalem', 'Asia/Jerusalem'), ('Asia/Kabul', 'Asia/Kabul'), ('Asia/Kamchatka', 'Asia/Kamchatka'), ('Asia/Karachi', 'Asia/Karachi'), ('Asia/Kathmandu', 'Asia/Kathmandu'), ('Asia/Khandyga', 'Asia/Khandyga'), ('Asia/Kolkata', 'Asia/Kolkata'), ('Asia/Krasnoyarsk', 'Asia/Krasnoyarsk'), ('Asia/Kuala_Lumpur', 'Asia/Kuala_Lumpur'), ('Asia/Kuching', 'Asia/Kuching'), ('Asia/Kuwait', 'Asia/Kuwait'), ('Asia/Macau', 'Asia/Macau'), ('Asia/Magadan', 'Asia/Magadan'), ('Asia/Makassar', 'Asia/Makassar'), ('Asia/Manila', 'Asia/Manila'), ('Asia/Muscat', 'Asia/Muscat'), ('Asia/Nicosia', 'Asia/Nicosia'), ('Asia/Novokuznetsk', 'Asia/Novokuznetsk'), ('Asia/Novosibirsk', 'Asia/Novosibirsk'), ('Asia/Omsk', 'Asia/Omsk'), ('Asia/Oral', 'Asia/Oral'), ('Asia/Phnom_Penh', 'Asia/Phnom_Penh'), ('Asia/Pontianak', 'Asia/Pontianak'), ('Asia/Pyongyang', 'Asia/Pyongyang'), ('Asia/Qatar', 'Asia/Qatar'), ('Asia/Qostanay', 'Asia/Qostanay'), ('Asia/Qyzylorda', 'Asia/Qyzylorda'), ('Asia/Riyadh', 'Asia/Riyadh'), ('Asia/Sakhalin', 'Asia/Sakhalin'), ('Asia/Samarkand', 'Asia/Samarkand'), ('Asia/Seoul', 'Asia/Seoul'), ('Asia/Shanghai', 'Asia/Shanghai'), ('Asia/Singapore', 'Asia/Singapore'), ('Asia/Srednekolymsk', 'Asia/Srednekolymsk'), ('Asia/Taipei', 'Asia/Taipei'), ('Asia/Tashkent', 'Asia/Tashkent'), ('Asia/Tbilisi', 'Asia/Tbilisi'), ('Asia/Tehran', 'Asia/Tehran'), ('Asia/Thimphu', 'Asia/Thimphu'), ('Asia/Tokyo', 'Asia/Tokyo'), ('Asia/Tomsk', 'Asia/Tomsk'), ('Asia/Ulaanbaatar', 'Asia/Ulaanbaatar'), ('Asia/Urumqi', 'Asia/Urumqi'), ('Asia/Ust-Nera', 'Asia/Ust-Nera'), ('Asia/Vientiane', 'Asia/Vientiane'), ('Asia/Vladivostok', 'Asia/Vladivostok'), ('Asia/Yakutsk', 'Asia/Yakutsk'), ('Asia/Yangon', 'Asia/Yangon'), ('Asia/Yekaterinburg', 'Asia/Yekaterinburg'), ('Asia/Yerevan', 'Asia/Yerevan'), ('Atlantic/Azores', 'Atlantic/Azores'), ('Atlantic/Bermuda', 'Atlantic/Bermuda'), ('Atlantic/Canary', 'Atlantic/Canary'), ('Atlantic/Cape_Verde', 'Atlantic/Cape_Verde'), ('Atlantic/Faroe', 'Atlantic/Faroe'), ('Atlantic/Madeira', 'Atlantic/Madeira'), ('Atlantic/Reykjavik', 'Atlantic/Reykjavik'), ('Atlantic/South_Georgia', 'Atlantic/South_Georgia'), ('Atlantic/St_Helena', 'Atlantic/St_Helena'), ('Atlantic/Stanley', 'Atlantic/Stanley'), ('Australia/Adelaide', 'Australia/Adelaide'), ('Australia/Brisbane', 'Australia/Brisbane'), ('Australia/Broken_Hill', 'Australia/Broken_Hill'), ('Australia/Currie', 'Australia/Currie'), ('Australia/Darwin', 'Australia/Darwin'), ('Australia/Eucla', 'Australia/Eucla'), ('Australia/Hobart', 'Australia/Hobart'), ('Australia/Lindeman', 'Australia/Lindeman'), ('Australia/Lord_Howe', 'Australia/Lord_Howe'), ('Australia/Melbourne', 'Australia/Melbourne'), ('Australia/Perth', 'Australia/Perth'), ('Australia/Sydney', 'Australia/Sydney'), ('Canada/Atlantic', 'Canada/Atlantic'), ('Canada/Central', 'Canada/Central'), ('Canada/Eastern', 'Canada/Eastern'), ('Canada/Mountain', 'Canada/Mountain'), ('Canada/Newfoundland', 'Canada/Newfoundland'), ('Canada/Pacific', 'Canada/Pacific'), ('Europe/Amsterdam', 'Europe/Amsterdam'), ('Europe/Andorra', 'Europe/Andorra'), ('Europe/Astrakhan', 'Europe/Astrakhan'), ('Europe/Athens', 'Europe/Athens'), ('Europe/Belgrade', 'Europe/Belgrade'), ('Europe/Berlin', 'Europe/Berlin'), ('Europe/Bratislava', 'Europe/Bratislava'), ('Europe/Brussels', 'Europe/Brussels'), ('Europe/Bucharest', 'Europe/Bucharest'), ('Europe/Budapest', 'Europe/Budapest'), ('Europe/Busingen', 'Europe/Busingen'), ('Europe/Chisinau', 'Europe/Chisinau'), ('Europe/Copenhagen', 'Europe/Copenhagen'), ('Europe/Dublin', 'Europe/Dublin'), ('Europe/Gibraltar', 'Europe/Gibraltar'), ('Europe/Guernsey', 'Europe/Guernsey'), ('Europe/Helsinki', 'Europe/Helsinki'), ('Europe/Isle_of_Man', 'Europe/Isle_of_Man'), ('Europe/Istanbul', 'Europe/Istanbul'), ('Europe/Jersey', 'Europe/Jersey'), ('Europe/Kaliningrad', 'Europe/Kaliningrad'), ('Europe/Kiev', 'Europe/Kiev'), ('Europe/Kirov', 'Europe/Kirov'), ('Europe/Lisbon', 'Europe/Lisbon'), ('Europe/Ljubljana', 'Europe/Ljubljana'), ('Europe/London', 'Europe/London'), ('Europe/Luxembourg', 'Europe/Luxembourg'), ('Europe/Madrid', 'Europe/Madrid'), ('Europe/Malta', 'Europe/Malta'), ('Europe/Mariehamn', 'Europe/Mariehamn'), ('Europe/Minsk', 'Europe/Minsk'), ('Europe/Monaco', 'Europe/Monaco'), ('Europe/Moscow', 'Europe/Moscow'), ('Europe/Oslo', 'Europe/Oslo'), ('Europe/Paris', 'Europe/Paris'), ('Europe/Podgorica', 'Europe/Podgorica'), ('Europe/Prague', 'Europe/Prague'), ('Europe/Riga', 'Europe/Riga'), ('Europe/Rome', 'Europe/Rome'), ('Europe/Samara', 'Europe/Samara'), ('Europe/San_Marino', 'Europe/San_Marino'), ('Europe/Sarajevo', 'Europe/Sarajevo'), ('Europe/Saratov', 'Europe/Saratov'), ('Europe/Simferopol', 'Europe/Simferopol'), ('Europe/Skopje', 'Europe/Skopje'), ('Europe/Sofia', 'Europe/Sofia'), ('Europe/Stockholm', 'Europe/Stockholm'), ('Europe/Tallinn', 'Europe/Tallinn'), ('Europe/Tirane', 'Europe/Tirane'), ('Europe/Ulyanovsk', 'Europe/Ulyanovsk'), ('Europe/Uzhgorod', 'Europe/Uzhgorod'), ('Europe/Vaduz', 'Europe/Vaduz'), ('Europe/Vatican', 'Europe/Vatican'), ('Europe/Vienna', 'Europe/Vienna'), ('Europe/Vilnius', 'Europe/Vilnius'), ('Europe/Volgograd', 'Europe/Volgograd'), ('Europe/Warsaw', 'Europe/Warsaw'), ('Europe/Zagreb', 'Europe/Zagreb'), ('Europe/Zaporozhye', 'Europe/Zaporozhye'), ('Europe/Zurich', 'Europe/Zurich'), ('GMT', 'GMT'), ('Indian/Antananarivo', 'Indian/Antananarivo'), ('Indian/Chagos', 'Indian/Chagos'), ('Indian/Christmas', 'Indian/Christmas'), ('Indian/Cocos', 'Indian/Cocos'), ('Indian/Comoro', 'Indian/Comoro'), ('Indian/Kerguelen', 'Indian/Kerguelen'), ('Indian/Mahe', 'Indian/Mahe'), ('Indian/Maldives', 'Indian/Maldives'), ('Indian/Mauritius', 'Indian/Mauritius'), ('Indian/Mayotte', 'Indian/Mayotte'), ('Indian/Reunion', 'Indian/Reunion'), ('Pacific/Apia', 'Pacific/Apia'), ('Pacific/Auckland', 'Pacific/Auckland'), ('Pacific/Bougainville', 'Pacific/Bougainville'), ('Pacific/Chatham', 'Pacific/Chatham'), ('Pacific/Chuuk', 'Pacific/Chuuk'), ('Pacific/Easter', 'Pacific/Easter'), ('Pacific/Efate', 'Pacific/Efate'), ('Pacific/Enderbury', 'Pacific/Enderbury'), ('Pacific/Fakaofo', 'Pacific/Fakaofo'), ('Pacific/Fiji', 'Pacific/Fiji'), ('Pacific/Funafuti', 'Pacific/Funafuti'), ('Pacific/Galapagos', 'Pacific/Galapagos'), ('Pacific/Gambier', 'Pacific/Gambier'), ('Pacific/Guadalcanal', 'Pacific/Guadalcanal'), ('Pacific/Guam', 'Pacific/Guam'), ('Pacific/Honolulu', 'Pacific/Honolulu'), ('Pacific/Kiritimati', 'Pacific/Kiritimati'), ('Pacific/Kosrae', 'Pacific/Kosrae'), ('Pacific/Kwajalein', 'Pacific/Kwajalein'), ('Pacific/Majuro', 'Pacific/Majuro'), ('Pacific/Marquesas', 'Pacific/Marquesas'), ('Pacific/Midway', 'Pacific/Midway'), ('Pacific/Nauru', 'Pacific/Nauru'), ('Pacific/Niue', 'Pacific/Niue'), ('Pacific/Norfolk', 'Pacific/Norfolk'), ('Pacific/Noumea', 'Pacific/Noumea'), ('Pacific/Pago_Pago', 'Pacific/Pago_Pago'), ('Pacific/Palau', 'Pacific/Palau'), ('Pacific/Pitcairn', 'Pacific/Pitcairn'), ('Pacific/Pohnpei', 'Pacific/Pohnpei'), ('Pacific/Port_Moresby', 'Pacific/Port_Moresby'), ('Pacific/Rarotonga', 'Pacific/Rarotonga'), ('Pacific/Saipan', 'Pacific/Saipan'), ('Pacific/Tahiti', 'Pacific/Tahiti'), ('Pacific/Tarawa', 'Pacific/Tarawa'), ('Pacific/Tongatapu', 'Pacific/Tongatapu'), ('Pacific/Wake', 'Pacific/Wake'), ('Pacific/Wallis', 'Pacific/Wallis'), ('US/Alaska', 'US/Alaska'), ('US/Arizona', 'US/Arizona'), ('US/Central', 'US/Central'), ('US/Eastern', 'US/Eastern'), ('US/Hawaii', 'US/Hawaii'), ('US/Mountain', 'US/Mountain'), ('US/Pacific', 'US/Pacific'), ('UTC', 'UTC')], default='UTC', help_text='Used for developer clock page', max_length=100),
+ field=models.CharField(
+ choices=[
+ ('Africa/Abidjan', 'Africa/Abidjan'),
+ ('Africa/Accra', 'Africa/Accra'),
+ ('Africa/Addis_Ababa', 'Africa/Addis_Ababa'),
+ ('Africa/Algiers', 'Africa/Algiers'),
+ ('Africa/Asmara', 'Africa/Asmara'),
+ ('Africa/Bamako', 'Africa/Bamako'),
+ ('Africa/Bangui', 'Africa/Bangui'),
+ ('Africa/Banjul', 'Africa/Banjul'),
+ ('Africa/Bissau', 'Africa/Bissau'),
+ ('Africa/Blantyre', 'Africa/Blantyre'),
+ ('Africa/Brazzaville', 'Africa/Brazzaville'),
+ ('Africa/Bujumbura', 'Africa/Bujumbura'),
+ ('Africa/Cairo', 'Africa/Cairo'),
+ ('Africa/Casablanca', 'Africa/Casablanca'),
+ ('Africa/Ceuta', 'Africa/Ceuta'),
+ ('Africa/Conakry', 'Africa/Conakry'),
+ ('Africa/Dakar', 'Africa/Dakar'),
+ ('Africa/Dar_es_Salaam', 'Africa/Dar_es_Salaam'),
+ ('Africa/Djibouti', 'Africa/Djibouti'),
+ ('Africa/Douala', 'Africa/Douala'),
+ ('Africa/El_Aaiun', 'Africa/El_Aaiun'),
+ ('Africa/Freetown', 'Africa/Freetown'),
+ ('Africa/Gaborone', 'Africa/Gaborone'),
+ ('Africa/Harare', 'Africa/Harare'),
+ ('Africa/Johannesburg', 'Africa/Johannesburg'),
+ ('Africa/Juba', 'Africa/Juba'),
+ ('Africa/Kampala', 'Africa/Kampala'),
+ ('Africa/Khartoum', 'Africa/Khartoum'),
+ ('Africa/Kigali', 'Africa/Kigali'),
+ ('Africa/Kinshasa', 'Africa/Kinshasa'),
+ ('Africa/Lagos', 'Africa/Lagos'),
+ ('Africa/Libreville', 'Africa/Libreville'),
+ ('Africa/Lome', 'Africa/Lome'),
+ ('Africa/Luanda', 'Africa/Luanda'),
+ ('Africa/Lubumbashi', 'Africa/Lubumbashi'),
+ ('Africa/Lusaka', 'Africa/Lusaka'),
+ ('Africa/Malabo', 'Africa/Malabo'),
+ ('Africa/Maputo', 'Africa/Maputo'),
+ ('Africa/Maseru', 'Africa/Maseru'),
+ ('Africa/Mbabane', 'Africa/Mbabane'),
+ ('Africa/Mogadishu', 'Africa/Mogadishu'),
+ ('Africa/Monrovia', 'Africa/Monrovia'),
+ ('Africa/Nairobi', 'Africa/Nairobi'),
+ ('Africa/Ndjamena', 'Africa/Ndjamena'),
+ ('Africa/Niamey', 'Africa/Niamey'),
+ ('Africa/Nouakchott', 'Africa/Nouakchott'),
+ ('Africa/Ouagadougou', 'Africa/Ouagadougou'),
+ ('Africa/Porto-Novo', 'Africa/Porto-Novo'),
+ ('Africa/Sao_Tome', 'Africa/Sao_Tome'),
+ ('Africa/Tripoli', 'Africa/Tripoli'),
+ ('Africa/Tunis', 'Africa/Tunis'),
+ ('Africa/Windhoek', 'Africa/Windhoek'),
+ ('America/Adak', 'America/Adak'),
+ ('America/Anchorage', 'America/Anchorage'),
+ ('America/Anguilla', 'America/Anguilla'),
+ ('America/Antigua', 'America/Antigua'),
+ ('America/Araguaina', 'America/Araguaina'),
+ ('America/Argentina/Buenos_Aires', 'America/Argentina/Buenos_Aires'),
+ ('America/Argentina/Catamarca', 'America/Argentina/Catamarca'),
+ ('America/Argentina/Cordoba', 'America/Argentina/Cordoba'),
+ ('America/Argentina/Jujuy', 'America/Argentina/Jujuy'),
+ ('America/Argentina/La_Rioja', 'America/Argentina/La_Rioja'),
+ ('America/Argentina/Mendoza', 'America/Argentina/Mendoza'),
+ ('America/Argentina/Rio_Gallegos', 'America/Argentina/Rio_Gallegos'),
+ ('America/Argentina/Salta', 'America/Argentina/Salta'),
+ ('America/Argentina/San_Juan', 'America/Argentina/San_Juan'),
+ ('America/Argentina/San_Luis', 'America/Argentina/San_Luis'),
+ ('America/Argentina/Tucuman', 'America/Argentina/Tucuman'),
+ ('America/Argentina/Ushuaia', 'America/Argentina/Ushuaia'),
+ ('America/Aruba', 'America/Aruba'),
+ ('America/Asuncion', 'America/Asuncion'),
+ ('America/Atikokan', 'America/Atikokan'),
+ ('America/Bahia', 'America/Bahia'),
+ ('America/Bahia_Banderas', 'America/Bahia_Banderas'),
+ ('America/Barbados', 'America/Barbados'),
+ ('America/Belem', 'America/Belem'),
+ ('America/Belize', 'America/Belize'),
+ ('America/Blanc-Sablon', 'America/Blanc-Sablon'),
+ ('America/Boa_Vista', 'America/Boa_Vista'),
+ ('America/Bogota', 'America/Bogota'),
+ ('America/Boise', 'America/Boise'),
+ ('America/Cambridge_Bay', 'America/Cambridge_Bay'),
+ ('America/Campo_Grande', 'America/Campo_Grande'),
+ ('America/Cancun', 'America/Cancun'),
+ ('America/Caracas', 'America/Caracas'),
+ ('America/Cayenne', 'America/Cayenne'),
+ ('America/Cayman', 'America/Cayman'),
+ ('America/Chicago', 'America/Chicago'),
+ ('America/Chihuahua', 'America/Chihuahua'),
+ ('America/Costa_Rica', 'America/Costa_Rica'),
+ ('America/Creston', 'America/Creston'),
+ ('America/Cuiaba', 'America/Cuiaba'),
+ ('America/Curacao', 'America/Curacao'),
+ ('America/Danmarkshavn', 'America/Danmarkshavn'),
+ ('America/Dawson', 'America/Dawson'),
+ ('America/Dawson_Creek', 'America/Dawson_Creek'),
+ ('America/Denver', 'America/Denver'),
+ ('America/Detroit', 'America/Detroit'),
+ ('America/Dominica', 'America/Dominica'),
+ ('America/Edmonton', 'America/Edmonton'),
+ ('America/Eirunepe', 'America/Eirunepe'),
+ ('America/El_Salvador', 'America/El_Salvador'),
+ ('America/Fort_Nelson', 'America/Fort_Nelson'),
+ ('America/Fortaleza', 'America/Fortaleza'),
+ ('America/Glace_Bay', 'America/Glace_Bay'),
+ ('America/Godthab', 'America/Godthab'),
+ ('America/Goose_Bay', 'America/Goose_Bay'),
+ ('America/Grand_Turk', 'America/Grand_Turk'),
+ ('America/Grenada', 'America/Grenada'),
+ ('America/Guadeloupe', 'America/Guadeloupe'),
+ ('America/Guatemala', 'America/Guatemala'),
+ ('America/Guayaquil', 'America/Guayaquil'),
+ ('America/Guyana', 'America/Guyana'),
+ ('America/Halifax', 'America/Halifax'),
+ ('America/Havana', 'America/Havana'),
+ ('America/Hermosillo', 'America/Hermosillo'),
+ ('America/Indiana/Indianapolis', 'America/Indiana/Indianapolis'),
+ ('America/Indiana/Knox', 'America/Indiana/Knox'),
+ ('America/Indiana/Marengo', 'America/Indiana/Marengo'),
+ ('America/Indiana/Petersburg', 'America/Indiana/Petersburg'),
+ ('America/Indiana/Tell_City', 'America/Indiana/Tell_City'),
+ ('America/Indiana/Vevay', 'America/Indiana/Vevay'),
+ ('America/Indiana/Vincennes', 'America/Indiana/Vincennes'),
+ ('America/Indiana/Winamac', 'America/Indiana/Winamac'),
+ ('America/Inuvik', 'America/Inuvik'),
+ ('America/Iqaluit', 'America/Iqaluit'),
+ ('America/Jamaica', 'America/Jamaica'),
+ ('America/Juneau', 'America/Juneau'),
+ ('America/Kentucky/Louisville', 'America/Kentucky/Louisville'),
+ ('America/Kentucky/Monticello', 'America/Kentucky/Monticello'),
+ ('America/Kralendijk', 'America/Kralendijk'),
+ ('America/La_Paz', 'America/La_Paz'),
+ ('America/Lima', 'America/Lima'),
+ ('America/Los_Angeles', 'America/Los_Angeles'),
+ ('America/Lower_Princes', 'America/Lower_Princes'),
+ ('America/Maceio', 'America/Maceio'),
+ ('America/Managua', 'America/Managua'),
+ ('America/Manaus', 'America/Manaus'),
+ ('America/Marigot', 'America/Marigot'),
+ ('America/Martinique', 'America/Martinique'),
+ ('America/Matamoros', 'America/Matamoros'),
+ ('America/Mazatlan', 'America/Mazatlan'),
+ ('America/Menominee', 'America/Menominee'),
+ ('America/Merida', 'America/Merida'),
+ ('America/Metlakatla', 'America/Metlakatla'),
+ ('America/Mexico_City', 'America/Mexico_City'),
+ ('America/Miquelon', 'America/Miquelon'),
+ ('America/Moncton', 'America/Moncton'),
+ ('America/Monterrey', 'America/Monterrey'),
+ ('America/Montevideo', 'America/Montevideo'),
+ ('America/Montserrat', 'America/Montserrat'),
+ ('America/Nassau', 'America/Nassau'),
+ ('America/New_York', 'America/New_York'),
+ ('America/Nipigon', 'America/Nipigon'),
+ ('America/Nome', 'America/Nome'),
+ ('America/Noronha', 'America/Noronha'),
+ ('America/North_Dakota/Beulah', 'America/North_Dakota/Beulah'),
+ ('America/North_Dakota/Center', 'America/North_Dakota/Center'),
+ ('America/North_Dakota/New_Salem', 'America/North_Dakota/New_Salem'),
+ ('America/Ojinaga', 'America/Ojinaga'),
+ ('America/Panama', 'America/Panama'),
+ ('America/Pangnirtung', 'America/Pangnirtung'),
+ ('America/Paramaribo', 'America/Paramaribo'),
+ ('America/Phoenix', 'America/Phoenix'),
+ ('America/Port-au-Prince', 'America/Port-au-Prince'),
+ ('America/Port_of_Spain', 'America/Port_of_Spain'),
+ ('America/Porto_Velho', 'America/Porto_Velho'),
+ ('America/Puerto_Rico', 'America/Puerto_Rico'),
+ ('America/Punta_Arenas', 'America/Punta_Arenas'),
+ ('America/Rainy_River', 'America/Rainy_River'),
+ ('America/Rankin_Inlet', 'America/Rankin_Inlet'),
+ ('America/Recife', 'America/Recife'),
+ ('America/Regina', 'America/Regina'),
+ ('America/Resolute', 'America/Resolute'),
+ ('America/Rio_Branco', 'America/Rio_Branco'),
+ ('America/Santarem', 'America/Santarem'),
+ ('America/Santiago', 'America/Santiago'),
+ ('America/Santo_Domingo', 'America/Santo_Domingo'),
+ ('America/Sao_Paulo', 'America/Sao_Paulo'),
+ ('America/Scoresbysund', 'America/Scoresbysund'),
+ ('America/Sitka', 'America/Sitka'),
+ ('America/St_Barthelemy', 'America/St_Barthelemy'),
+ ('America/St_Johns', 'America/St_Johns'),
+ ('America/St_Kitts', 'America/St_Kitts'),
+ ('America/St_Lucia', 'America/St_Lucia'),
+ ('America/St_Thomas', 'America/St_Thomas'),
+ ('America/St_Vincent', 'America/St_Vincent'),
+ ('America/Swift_Current', 'America/Swift_Current'),
+ ('America/Tegucigalpa', 'America/Tegucigalpa'),
+ ('America/Thule', 'America/Thule'),
+ ('America/Thunder_Bay', 'America/Thunder_Bay'),
+ ('America/Tijuana', 'America/Tijuana'),
+ ('America/Toronto', 'America/Toronto'),
+ ('America/Tortola', 'America/Tortola'),
+ ('America/Vancouver', 'America/Vancouver'),
+ ('America/Whitehorse', 'America/Whitehorse'),
+ ('America/Winnipeg', 'America/Winnipeg'),
+ ('America/Yakutat', 'America/Yakutat'),
+ ('America/Yellowknife', 'America/Yellowknife'),
+ ('Antarctica/Casey', 'Antarctica/Casey'),
+ ('Antarctica/Davis', 'Antarctica/Davis'),
+ ('Antarctica/DumontDUrville', 'Antarctica/DumontDUrville'),
+ ('Antarctica/Macquarie', 'Antarctica/Macquarie'),
+ ('Antarctica/Mawson', 'Antarctica/Mawson'),
+ ('Antarctica/McMurdo', 'Antarctica/McMurdo'),
+ ('Antarctica/Palmer', 'Antarctica/Palmer'),
+ ('Antarctica/Rothera', 'Antarctica/Rothera'),
+ ('Antarctica/Syowa', 'Antarctica/Syowa'),
+ ('Antarctica/Troll', 'Antarctica/Troll'),
+ ('Antarctica/Vostok', 'Antarctica/Vostok'),
+ ('Arctic/Longyearbyen', 'Arctic/Longyearbyen'),
+ ('Asia/Aden', 'Asia/Aden'),
+ ('Asia/Almaty', 'Asia/Almaty'),
+ ('Asia/Amman', 'Asia/Amman'),
+ ('Asia/Anadyr', 'Asia/Anadyr'),
+ ('Asia/Aqtau', 'Asia/Aqtau'),
+ ('Asia/Aqtobe', 'Asia/Aqtobe'),
+ ('Asia/Ashgabat', 'Asia/Ashgabat'),
+ ('Asia/Atyrau', 'Asia/Atyrau'),
+ ('Asia/Baghdad', 'Asia/Baghdad'),
+ ('Asia/Bahrain', 'Asia/Bahrain'),
+ ('Asia/Baku', 'Asia/Baku'),
+ ('Asia/Bangkok', 'Asia/Bangkok'),
+ ('Asia/Barnaul', 'Asia/Barnaul'),
+ ('Asia/Beirut', 'Asia/Beirut'),
+ ('Asia/Bishkek', 'Asia/Bishkek'),
+ ('Asia/Brunei', 'Asia/Brunei'),
+ ('Asia/Chita', 'Asia/Chita'),
+ ('Asia/Choibalsan', 'Asia/Choibalsan'),
+ ('Asia/Colombo', 'Asia/Colombo'),
+ ('Asia/Damascus', 'Asia/Damascus'),
+ ('Asia/Dhaka', 'Asia/Dhaka'),
+ ('Asia/Dili', 'Asia/Dili'),
+ ('Asia/Dubai', 'Asia/Dubai'),
+ ('Asia/Dushanbe', 'Asia/Dushanbe'),
+ ('Asia/Famagusta', 'Asia/Famagusta'),
+ ('Asia/Gaza', 'Asia/Gaza'),
+ ('Asia/Hebron', 'Asia/Hebron'),
+ ('Asia/Ho_Chi_Minh', 'Asia/Ho_Chi_Minh'),
+ ('Asia/Hong_Kong', 'Asia/Hong_Kong'),
+ ('Asia/Hovd', 'Asia/Hovd'),
+ ('Asia/Irkutsk', 'Asia/Irkutsk'),
+ ('Asia/Jakarta', 'Asia/Jakarta'),
+ ('Asia/Jayapura', 'Asia/Jayapura'),
+ ('Asia/Jerusalem', 'Asia/Jerusalem'),
+ ('Asia/Kabul', 'Asia/Kabul'),
+ ('Asia/Kamchatka', 'Asia/Kamchatka'),
+ ('Asia/Karachi', 'Asia/Karachi'),
+ ('Asia/Kathmandu', 'Asia/Kathmandu'),
+ ('Asia/Khandyga', 'Asia/Khandyga'),
+ ('Asia/Kolkata', 'Asia/Kolkata'),
+ ('Asia/Krasnoyarsk', 'Asia/Krasnoyarsk'),
+ ('Asia/Kuala_Lumpur', 'Asia/Kuala_Lumpur'),
+ ('Asia/Kuching', 'Asia/Kuching'),
+ ('Asia/Kuwait', 'Asia/Kuwait'),
+ ('Asia/Macau', 'Asia/Macau'),
+ ('Asia/Magadan', 'Asia/Magadan'),
+ ('Asia/Makassar', 'Asia/Makassar'),
+ ('Asia/Manila', 'Asia/Manila'),
+ ('Asia/Muscat', 'Asia/Muscat'),
+ ('Asia/Nicosia', 'Asia/Nicosia'),
+ ('Asia/Novokuznetsk', 'Asia/Novokuznetsk'),
+ ('Asia/Novosibirsk', 'Asia/Novosibirsk'),
+ ('Asia/Omsk', 'Asia/Omsk'),
+ ('Asia/Oral', 'Asia/Oral'),
+ ('Asia/Phnom_Penh', 'Asia/Phnom_Penh'),
+ ('Asia/Pontianak', 'Asia/Pontianak'),
+ ('Asia/Pyongyang', 'Asia/Pyongyang'),
+ ('Asia/Qatar', 'Asia/Qatar'),
+ ('Asia/Qostanay', 'Asia/Qostanay'),
+ ('Asia/Qyzylorda', 'Asia/Qyzylorda'),
+ ('Asia/Riyadh', 'Asia/Riyadh'),
+ ('Asia/Sakhalin', 'Asia/Sakhalin'),
+ ('Asia/Samarkand', 'Asia/Samarkand'),
+ ('Asia/Seoul', 'Asia/Seoul'),
+ ('Asia/Shanghai', 'Asia/Shanghai'),
+ ('Asia/Singapore', 'Asia/Singapore'),
+ ('Asia/Srednekolymsk', 'Asia/Srednekolymsk'),
+ ('Asia/Taipei', 'Asia/Taipei'),
+ ('Asia/Tashkent', 'Asia/Tashkent'),
+ ('Asia/Tbilisi', 'Asia/Tbilisi'),
+ ('Asia/Tehran', 'Asia/Tehran'),
+ ('Asia/Thimphu', 'Asia/Thimphu'),
+ ('Asia/Tokyo', 'Asia/Tokyo'),
+ ('Asia/Tomsk', 'Asia/Tomsk'),
+ ('Asia/Ulaanbaatar', 'Asia/Ulaanbaatar'),
+ ('Asia/Urumqi', 'Asia/Urumqi'),
+ ('Asia/Ust-Nera', 'Asia/Ust-Nera'),
+ ('Asia/Vientiane', 'Asia/Vientiane'),
+ ('Asia/Vladivostok', 'Asia/Vladivostok'),
+ ('Asia/Yakutsk', 'Asia/Yakutsk'),
+ ('Asia/Yangon', 'Asia/Yangon'),
+ ('Asia/Yekaterinburg', 'Asia/Yekaterinburg'),
+ ('Asia/Yerevan', 'Asia/Yerevan'),
+ ('Atlantic/Azores', 'Atlantic/Azores'),
+ ('Atlantic/Bermuda', 'Atlantic/Bermuda'),
+ ('Atlantic/Canary', 'Atlantic/Canary'),
+ ('Atlantic/Cape_Verde', 'Atlantic/Cape_Verde'),
+ ('Atlantic/Faroe', 'Atlantic/Faroe'),
+ ('Atlantic/Madeira', 'Atlantic/Madeira'),
+ ('Atlantic/Reykjavik', 'Atlantic/Reykjavik'),
+ ('Atlantic/South_Georgia', 'Atlantic/South_Georgia'),
+ ('Atlantic/St_Helena', 'Atlantic/St_Helena'),
+ ('Atlantic/Stanley', 'Atlantic/Stanley'),
+ ('Australia/Adelaide', 'Australia/Adelaide'),
+ ('Australia/Brisbane', 'Australia/Brisbane'),
+ ('Australia/Broken_Hill', 'Australia/Broken_Hill'),
+ ('Australia/Currie', 'Australia/Currie'),
+ ('Australia/Darwin', 'Australia/Darwin'),
+ ('Australia/Eucla', 'Australia/Eucla'),
+ ('Australia/Hobart', 'Australia/Hobart'),
+ ('Australia/Lindeman', 'Australia/Lindeman'),
+ ('Australia/Lord_Howe', 'Australia/Lord_Howe'),
+ ('Australia/Melbourne', 'Australia/Melbourne'),
+ ('Australia/Perth', 'Australia/Perth'),
+ ('Australia/Sydney', 'Australia/Sydney'),
+ ('Canada/Atlantic', 'Canada/Atlantic'),
+ ('Canada/Central', 'Canada/Central'),
+ ('Canada/Eastern', 'Canada/Eastern'),
+ ('Canada/Mountain', 'Canada/Mountain'),
+ ('Canada/Newfoundland', 'Canada/Newfoundland'),
+ ('Canada/Pacific', 'Canada/Pacific'),
+ ('Europe/Amsterdam', 'Europe/Amsterdam'),
+ ('Europe/Andorra', 'Europe/Andorra'),
+ ('Europe/Astrakhan', 'Europe/Astrakhan'),
+ ('Europe/Athens', 'Europe/Athens'),
+ ('Europe/Belgrade', 'Europe/Belgrade'),
+ ('Europe/Berlin', 'Europe/Berlin'),
+ ('Europe/Bratislava', 'Europe/Bratislava'),
+ ('Europe/Brussels', 'Europe/Brussels'),
+ ('Europe/Bucharest', 'Europe/Bucharest'),
+ ('Europe/Budapest', 'Europe/Budapest'),
+ ('Europe/Busingen', 'Europe/Busingen'),
+ ('Europe/Chisinau', 'Europe/Chisinau'),
+ ('Europe/Copenhagen', 'Europe/Copenhagen'),
+ ('Europe/Dublin', 'Europe/Dublin'),
+ ('Europe/Gibraltar', 'Europe/Gibraltar'),
+ ('Europe/Guernsey', 'Europe/Guernsey'),
+ ('Europe/Helsinki', 'Europe/Helsinki'),
+ ('Europe/Isle_of_Man', 'Europe/Isle_of_Man'),
+ ('Europe/Istanbul', 'Europe/Istanbul'),
+ ('Europe/Jersey', 'Europe/Jersey'),
+ ('Europe/Kaliningrad', 'Europe/Kaliningrad'),
+ ('Europe/Kiev', 'Europe/Kiev'),
+ ('Europe/Kirov', 'Europe/Kirov'),
+ ('Europe/Lisbon', 'Europe/Lisbon'),
+ ('Europe/Ljubljana', 'Europe/Ljubljana'),
+ ('Europe/London', 'Europe/London'),
+ ('Europe/Luxembourg', 'Europe/Luxembourg'),
+ ('Europe/Madrid', 'Europe/Madrid'),
+ ('Europe/Malta', 'Europe/Malta'),
+ ('Europe/Mariehamn', 'Europe/Mariehamn'),
+ ('Europe/Minsk', 'Europe/Minsk'),
+ ('Europe/Monaco', 'Europe/Monaco'),
+ ('Europe/Moscow', 'Europe/Moscow'),
+ ('Europe/Oslo', 'Europe/Oslo'),
+ ('Europe/Paris', 'Europe/Paris'),
+ ('Europe/Podgorica', 'Europe/Podgorica'),
+ ('Europe/Prague', 'Europe/Prague'),
+ ('Europe/Riga', 'Europe/Riga'),
+ ('Europe/Rome', 'Europe/Rome'),
+ ('Europe/Samara', 'Europe/Samara'),
+ ('Europe/San_Marino', 'Europe/San_Marino'),
+ ('Europe/Sarajevo', 'Europe/Sarajevo'),
+ ('Europe/Saratov', 'Europe/Saratov'),
+ ('Europe/Simferopol', 'Europe/Simferopol'),
+ ('Europe/Skopje', 'Europe/Skopje'),
+ ('Europe/Sofia', 'Europe/Sofia'),
+ ('Europe/Stockholm', 'Europe/Stockholm'),
+ ('Europe/Tallinn', 'Europe/Tallinn'),
+ ('Europe/Tirane', 'Europe/Tirane'),
+ ('Europe/Ulyanovsk', 'Europe/Ulyanovsk'),
+ ('Europe/Uzhgorod', 'Europe/Uzhgorod'),
+ ('Europe/Vaduz', 'Europe/Vaduz'),
+ ('Europe/Vatican', 'Europe/Vatican'),
+ ('Europe/Vienna', 'Europe/Vienna'),
+ ('Europe/Vilnius', 'Europe/Vilnius'),
+ ('Europe/Volgograd', 'Europe/Volgograd'),
+ ('Europe/Warsaw', 'Europe/Warsaw'),
+ ('Europe/Zagreb', 'Europe/Zagreb'),
+ ('Europe/Zaporozhye', 'Europe/Zaporozhye'),
+ ('Europe/Zurich', 'Europe/Zurich'),
+ ('GMT', 'GMT'),
+ ('Indian/Antananarivo', 'Indian/Antananarivo'),
+ ('Indian/Chagos', 'Indian/Chagos'),
+ ('Indian/Christmas', 'Indian/Christmas'),
+ ('Indian/Cocos', 'Indian/Cocos'),
+ ('Indian/Comoro', 'Indian/Comoro'),
+ ('Indian/Kerguelen', 'Indian/Kerguelen'),
+ ('Indian/Mahe', 'Indian/Mahe'),
+ ('Indian/Maldives', 'Indian/Maldives'),
+ ('Indian/Mauritius', 'Indian/Mauritius'),
+ ('Indian/Mayotte', 'Indian/Mayotte'),
+ ('Indian/Reunion', 'Indian/Reunion'),
+ ('Pacific/Apia', 'Pacific/Apia'),
+ ('Pacific/Auckland', 'Pacific/Auckland'),
+ ('Pacific/Bougainville', 'Pacific/Bougainville'),
+ ('Pacific/Chatham', 'Pacific/Chatham'),
+ ('Pacific/Chuuk', 'Pacific/Chuuk'),
+ ('Pacific/Easter', 'Pacific/Easter'),
+ ('Pacific/Efate', 'Pacific/Efate'),
+ ('Pacific/Enderbury', 'Pacific/Enderbury'),
+ ('Pacific/Fakaofo', 'Pacific/Fakaofo'),
+ ('Pacific/Fiji', 'Pacific/Fiji'),
+ ('Pacific/Funafuti', 'Pacific/Funafuti'),
+ ('Pacific/Galapagos', 'Pacific/Galapagos'),
+ ('Pacific/Gambier', 'Pacific/Gambier'),
+ ('Pacific/Guadalcanal', 'Pacific/Guadalcanal'),
+ ('Pacific/Guam', 'Pacific/Guam'),
+ ('Pacific/Honolulu', 'Pacific/Honolulu'),
+ ('Pacific/Kiritimati', 'Pacific/Kiritimati'),
+ ('Pacific/Kosrae', 'Pacific/Kosrae'),
+ ('Pacific/Kwajalein', 'Pacific/Kwajalein'),
+ ('Pacific/Majuro', 'Pacific/Majuro'),
+ ('Pacific/Marquesas', 'Pacific/Marquesas'),
+ ('Pacific/Midway', 'Pacific/Midway'),
+ ('Pacific/Nauru', 'Pacific/Nauru'),
+ ('Pacific/Niue', 'Pacific/Niue'),
+ ('Pacific/Norfolk', 'Pacific/Norfolk'),
+ ('Pacific/Noumea', 'Pacific/Noumea'),
+ ('Pacific/Pago_Pago', 'Pacific/Pago_Pago'),
+ ('Pacific/Palau', 'Pacific/Palau'),
+ ('Pacific/Pitcairn', 'Pacific/Pitcairn'),
+ ('Pacific/Pohnpei', 'Pacific/Pohnpei'),
+ ('Pacific/Port_Moresby', 'Pacific/Port_Moresby'),
+ ('Pacific/Rarotonga', 'Pacific/Rarotonga'),
+ ('Pacific/Saipan', 'Pacific/Saipan'),
+ ('Pacific/Tahiti', 'Pacific/Tahiti'),
+ ('Pacific/Tarawa', 'Pacific/Tarawa'),
+ ('Pacific/Tongatapu', 'Pacific/Tongatapu'),
+ ('Pacific/Wake', 'Pacific/Wake'),
+ ('Pacific/Wallis', 'Pacific/Wallis'),
+ ('US/Alaska', 'US/Alaska'),
+ ('US/Arizona', 'US/Arizona'),
+ ('US/Central', 'US/Central'),
+ ('US/Eastern', 'US/Eastern'),
+ ('US/Hawaii', 'US/Hawaii'),
+ ('US/Mountain', 'US/Mountain'),
+ ('US/Pacific', 'US/Pacific'),
+ ('UTC', 'UTC')],
+ default='UTC', help_text='Used for developer clock page', max_length=100),
),
]
diff --git a/devel/migrations/0005_auto_20200628_1600.py b/devel/migrations/0005_auto_20200628_1600.py
index af4188b7..d52114e7 100644
--- a/devel/migrations/0005_auto_20200628_1600.py
+++ b/devel/migrations/0005_auto_20200628_1600.py
@@ -13,6 +13,8 @@ class Migration(migrations.Migration):
migrations.AlterField(
model_name='userprofile',
name='website_rss',
- field=models.CharField(blank=True, help_text='RSS Feed of your website for planet.archlinux.org', max_length=200, null=True),
+ field=models.CharField(
+ blank=True, help_text='RSS Feed of your website for planet.archlinux.org',
+ max_length=200, null=True),
),
]
diff --git a/devel/models.py b/devel/models.py
index 59324746..ed87fa8a 100644
--- a/devel/models.py
+++ b/devel/models.py
@@ -30,7 +30,8 @@ class UserProfile(models.Model):
max_length=50,
help_text="Required field")
other_contact = models.CharField(max_length=100, null=True, blank=True)
- pgp_key = PGPKeyField(max_length=40, null=True, blank=True,
+ pgp_key = PGPKeyField(
+ max_length=40, null=True, blank=True,
verbose_name="PGP key fingerprint",
help_text="consists of 40 hex digits; use `gpg --fingerprint`")
website = models.CharField(max_length=200, null=True, blank=True)
@@ -44,14 +45,14 @@ class UserProfile(models.Model):
occupation = models.CharField(max_length=50, null=True, blank=True)
roles = models.CharField(max_length=255, null=True, blank=True)
favorite_distros = models.CharField(max_length=255, null=True, blank=True)
- picture = models.FileField(upload_to='devs', default='devs/silhouette.png',
- help_text="Ideally 125px by 125px")
+ picture = models.FileField(
+ upload_to='devs', default='devs/silhouette.png', help_text="Ideally 125px by 125px")
user = models.OneToOneField(User, related_name='userprofile', on_delete=models.CASCADE)
allowed_repos = models.ManyToManyField('main.Repo', blank=True)
- latin_name = models.CharField(max_length=255, null=True, blank=True,
- help_text="Latin-form name; used only for non-Latin full names")
- rebuilderd_updates = models.BooleanField(default=False,
- help_text='Receive reproducible build package updates')
+ latin_name = models.CharField(
+ max_length=255, null=True, blank=True, help_text="Latin-form name; used only for non-Latin full names")
+ rebuilderd_updates = models.BooleanField(
+ default=False, help_text='Receive reproducible build package updates')
last_modified = models.DateTimeField(editable=False)
class Meta:
@@ -87,11 +88,16 @@ class StaffGroup(models.Model):
class MasterKey(models.Model):
- owner = models.ForeignKey(User, related_name='masterkey_owner',
- help_text="The developer holding this master key", on_delete=models.CASCADE)
- revoker = models.ForeignKey(User, related_name='masterkey_revoker',
- help_text="The developer holding the revocation certificate", on_delete=models.CASCADE)
- pgp_key = PGPKeyField(max_length=40, verbose_name="PGP key fingerprint",
+ owner = models.ForeignKey(
+ User, related_name='masterkey_owner',
+ help_text="The developer holding this master key",
+ on_delete=models.CASCADE)
+ revoker = models.ForeignKey(
+ User, related_name='masterkey_revoker',
+ help_text="The developer holding the revocation certificate",
+ on_delete=models.CASCADE)
+ pgp_key = PGPKeyField(
+ max_length=40, verbose_name="PGP key fingerprint",
help_text="consists of 40 hex digits; use `gpg --fingerprint`")
created = models.DateField()
revoked = models.DateField(null=True, blank=True)
@@ -101,15 +107,15 @@ class MasterKey(models.Model):
get_latest_by = 'created'
def __str__(self):
- return '%s, created %s' % (
- self.owner.get_full_name(), self.created)
+ return '%s, created %s' % (self.owner.get_full_name(), self.created)
class DeveloperKey(models.Model):
- owner = models.ForeignKey(User, related_name='all_keys', null=True,
- help_text="The developer this key belongs to", on_delete=models.CASCADE)
- key = PGPKeyField(max_length=40, verbose_name="PGP key fingerprint",
- unique=True)
+ owner = models.ForeignKey(
+ User, related_name='all_keys', null=True,
+ help_text="The developer this key belongs to",
+ on_delete=models.CASCADE)
+ key = PGPKeyField(max_length=40, verbose_name="PGP key fingerprint", unique=True)
created = models.DateTimeField()
expires = models.DateTimeField(null=True, blank=True)
revoked = models.DateTimeField(null=True, blank=True)
@@ -120,10 +126,8 @@ class DeveloperKey(models.Model):
class PGPSignature(models.Model):
- signer = PGPKeyField(max_length=40, verbose_name="Signer key fingerprint",
- db_index=True)
- signee = PGPKeyField(max_length=40, verbose_name="Signee key fingerprint",
- db_index=True)
+ signer = PGPKeyField(max_length=40, verbose_name="Signer key fingerprint", db_index=True)
+ signee = PGPKeyField(max_length=40, verbose_name="Signee key fingerprint", db_index=True)
created = models.DateField()
expires = models.DateField(null=True, blank=True)
revoked = models.DateField(null=True, blank=True)
@@ -193,10 +197,8 @@ def delete_feed_model(sender, **kwargs):
Feed.objects.filter(website_rss=userprofile.website_rss).delete()
-pre_save.connect(create_feed_model, sender=UserProfile,
- dispatch_uid="devel.models")
+pre_save.connect(create_feed_model, sender=UserProfile, dispatch_uid="devel.models")
-post_save.connect(delete_feed_model, sender=User,
- dispatch_uid='main.models')
+post_save.connect(delete_feed_model, sender=User, dispatch_uid='main.models')
# vim: set ts=4 sw=4 et:
diff --git a/devel/reports.py b/devel/reports.py
index 2831840a..f163f050 100644
--- a/devel/reports.py
+++ b/devel/reports.py
@@ -203,8 +203,7 @@ REPORT_INFO = DeveloperReport('uncompressed-info', 'Uncompressed Info Pages',
REPORT_ORPHANS = DeveloperReport(
'unneeded-orphans',
'Unneeded Orphans',
- 'Packages that have no maintainer and are not required by any ' +
- 'other package in any repository',
+ 'Packages that have no maintainer and are not required by any other package in any repository',
unneeded_orphans,
personal=False)
@@ -215,8 +214,8 @@ REPORT_SIGNATURE = DeveloperReport(
REPORT_SIG_TIME = DeveloperReport(
'signature-time', 'Signature Time',
- 'Packages where the signature timestamp is more than 24 hours ' +
- 'after the build timestamp', signature_time,
+ 'Packages where the signature timestamp is more than 24 hours after the build timestamp',
+ signature_time,
['Signature Date', 'Packager'], ['sig_date', 'packager'])
NON_EXISTING_DEPENDENCIES = DeveloperReport(
@@ -232,8 +231,7 @@ REBUILDERD_PACKAGES = DeveloperReport(
'non-reproducible-packages',
'Non Reproducible package',
'Packages that are not reproducible on our reproducible.archlinux.org test environment',
- non_reproducible_packages,
- )
+ non_reproducible_packages)
def available_reports():
diff --git a/devel/templatetags/group.py b/devel/templatetags/group.py
index 2133d2f8..4467d2f4 100644
--- a/devel/templatetags/group.py
+++ b/devel/templatetags/group.py
@@ -2,6 +2,7 @@ from django import template
register = template.Library()
+
@register.filter(name='in_group')
def in_group(user, group_name):
return user.groups.filter(name=group_name).exists()
diff --git a/devel/tests/test_devel.py b/devel/tests/test_devel.py
index c8a28c1a..57a03788 100644
--- a/devel/tests/test_devel.py
+++ b/devel/tests/test_devel.py
@@ -19,8 +19,8 @@ class DevelView(TransactionTestCase):
self.profile = UserProfile.objects.create(user=self.user,
public_email="{}@awesome.com".format(self.user.username))
self.client.post('/login/', {
- 'username': self.user.username,
- 'password': password
+ 'username': self.user.username,
+ 'password': password
})
def tearDown(self):
diff --git a/devel/tests/test_pgp_import.py b/devel/tests/test_pgp_import.py
index f01e73a3..2748d8b1 100644
--- a/devel/tests/test_pgp_import.py
+++ b/devel/tests/test_pgp_import.py
@@ -12,10 +12,10 @@ ID2 = 'D8AFDDA07A5B6EDFA7D8CCDAD6D055F927843F1C'
ID3 = 'B588C0234ECADD3F0BBBEEBA44F9F02E089294E7'
SIG_DATA = [
- 'pub:-:4096:1:{id1}:{created}:::-:::scESCA::::::23::0:'.format(id1=ID1, created=CREATED),
- 'fpr:::::::::{id2}:'.format(id2=ID2),
- 'uid:-::::{created}::{id3}::{user}::::::::::0:'.format(created=CREATED, id3=ID3, user=USER),
- 'sig:::1:{id1}:{created}::::{user}:13x::{id2}:::10:'.format(id1=ID1, created=CREATED, user=USER, id2=ID2)
+ 'pub:-:4096:1:{id1}:{created}:::-:::scESCA::::::23::0:'.format(id1=ID1, created=CREATED),
+ 'fpr:::::::::{id2}:'.format(id2=ID2),
+ 'uid:-::::{created}::{id3}::{user}::::::::::0:'.format(created=CREATED, id3=ID3, user=USER),
+ 'sig:::1:{id1}:{created}::::{user}:13x::{id2}:::10:'.format(id1=ID1, created=CREATED, user=USER, id2=ID2)
]
diff --git a/devel/tests/test_reporead.py b/devel/tests/test_reporead.py
index 0ffe3a17..5e92dd56 100644
--- a/devel/tests/test_reporead.py
+++ b/devel/tests/test_reporead.py
@@ -24,10 +24,10 @@ class RepoReadTest(TransactionTestCase):
arch = Arch.objects.get(name__iexact='any')
now = datetime.now(tz=timezone.utc)
return Package.objects.create(arch=arch, repo=repo, pkgname='systemd',
- pkgbase='systemd', pkgver=pkgver,
- pkgrel=pkgrel, pkgdesc='Linux kernel',
- compressed_size=10, installed_size=20,
- last_update=now, created=now)
+ pkgbase='systemd', pkgver=pkgver,
+ pkgrel=pkgrel, pkgdesc='Linux kernel',
+ compressed_size=10, installed_size=20,
+ last_update=now, created=now)
def test_invalid_args(self):
with self.assertRaises(CommandError) as e:
@@ -41,12 +41,12 @@ class RepoReadTest(TransactionTestCase):
with self.assertRaises(CommandError) as e:
call_command('reporead', 'x86_64', 'nothing.db.tar.gz')
self.assertIn('Specified package database file does not exist.', str(e.exception))
-
+
def test_invalid_arch(self):
with self.assertRaises(CommandError) as e:
call_command('reporead', 'armv64', 'devel/fixtures/core.db.tar.gz')
self.assertEqual('Specified architecture armv64 is not currently known.', str(e.exception))
-
+
def test_read_packages(self):
with patch('devel.management.commands.reporead.logger') as logger:
call_command('reporead', 'x86_64', 'devel/fixtures/core.db.tar.gz')
@@ -54,7 +54,8 @@ class RepoReadTest(TransactionTestCase):
# Verify contents
with tarfile.open('devel/fixtures/core.db.tar.gz') as tar:
- files = [name.replace('core.db/', '') for name in tar.getnames() if name != 'core.db' and not 'desc' in name]
+ files = [name.replace('core.db/', '') for name in tar.getnames()
+ if name != 'core.db' and 'desc' not in name]
packages = Package.objects.all()
import_packages = ["{}-{}-{}".format(pkg.pkgname, pkg.pkgver, pkg.pkgrel) for pkg in packages]
@@ -89,6 +90,6 @@ class RepoReadTest(TransactionTestCase):
call_command('reporead', 'x86_64', 'devel/fixtures/core.db.tar.gz')
logger.info.assert_called()
- objects = FlagRequest.objects.all()
+ objects = FlagRequest.objects.all()
self.assertEqual(len(objects), 1)
self.assertEqual(objects[0].pkgver, staging_pkg.pkgver)
diff --git a/devel/tests/test_reports.py b/devel/tests/test_reports.py
index 2906d940..70ee7df6 100644
--- a/devel/tests/test_reports.py
+++ b/devel/tests/test_reports.py
@@ -12,8 +12,8 @@ class DeveloperReport(TransactionTestCase):
'admin@archlinux.org',
password)
self.client.post('/login/', {
- 'username': self.user.username,
- 'password': password
+ 'username': self.user.username,
+ 'password': password
})
def tearDown(self):
diff --git a/devel/tests/test_retire_user.py b/devel/tests/test_retire_user.py
index 4e1c3985..ac5f26a6 100644
--- a/devel/tests/test_retire_user.py
+++ b/devel/tests/test_retire_user.py
@@ -11,11 +11,10 @@ from devel.models import UserProfile
class RetireUsertest(TransactionTestCase):
fixtures = ['main/fixtures/arches.json', 'main/fixtures/repos.json']
-
def setUp(self):
self.username = 'joe'
self.user = User.objects.create(username=self.username, first_name="Joe",
- last_name="User", email="user1@example.com")
+ last_name="User", email="user1@example.com")
self.profile = UserProfile.objects.create(user=self.user,
public_email="{}@awesome.com".format(self.user.username))
@@ -38,7 +37,7 @@ class RetireUsertest(TransactionTestCase):
def test_userprofile_missing(self):
user = User.objects.create(username='user2', first_name="Jane",
- last_name="User2", email="user2@example.com")
+ last_name="User2", email="user2@example.com")
with self.assertRaises(CommandError) as e:
call_command('retire_user', user.username)
diff --git a/devel/tests/test_user.py b/devel/tests/test_user.py
index 91c0b1e6..557b2abb 100644
--- a/devel/tests/test_user.py
+++ b/devel/tests/test_user.py
@@ -4,6 +4,7 @@ from django.test import TestCase
from devel.utils import UserFinder
from devel.models import UserProfile
+
class DevelTest(TestCase):
def test_index(self):
response = self.client.get('/devel/')
@@ -36,26 +37,27 @@ class DevelTest(TestCase):
response = self.client.get('/devel/admin_log', follow=True)
self.assertEqual(response.status_code, 200)
+
class FindUserTest(TestCase):
def setUp(self):
self.finder = UserFinder()
- self.user1 = User.objects.create(username="joeuser", first_name="Joe",
- last_name="User", email="user1@example.com")
- self.user2 = User.objects.create(username="john", first_name="John",
- last_name="", email="user2@example.com")
- self.user3 = User.objects.create(username="bjones", first_name="Bob",
- last_name="Jones", email="user3@example.com")
+ self.user1 = User.objects.create(
+ username="joeuser", first_name="Joe", last_name="User", email="user1@example.com")
+ self.user2 = User.objects.create(
+ username="john", first_name="John", last_name="", email="user2@example.com")
+ self.user3 = User.objects.create(
+ username="bjones", first_name="Bob", last_name="Jones", email="user3@example.com")
for user in (self.user1, self.user2, self.user3):
email_addr = "%s@awesome.com" % user.username
UserProfile.objects.create(user=user, public_email=email_addr)
- self.user4 = User.objects.create(username="tim1", first_name="Tim",
- last_name="One", email="tim@example.com")
- self.user5 = User.objects.create(username="tim2", first_name="Tim",
- last_name="Two", email="timtwo@example.com")
+ self.user4 = User.objects.create(
+ username="tim1", first_name="Tim", last_name="One", email="tim@example.com")
+ self.user5 = User.objects.create(
+ username="tim2", first_name="Tim", last_name="Two", email="timtwo@example.com")
def test_not_matching(self):
self.assertIsNone(self.finder.find(None))
@@ -68,54 +70,54 @@ class FindUserTest(TestCase):
self.assertIsNone(self.finder.find("Unknown Packager"))
def test_by_email(self):
- self.assertEqual(self.user1,
- self.finder.find("XXX YYY <user1@example.com>"))
- self.assertEqual(self.user2,
- self.finder.find("YYY ZZZ <user2@example.com>"))
+ self.assertEqual(
+ self.user1, self.finder.find("XXX YYY <user1@example.com>"))
+ self.assertEqual(
+ self.user2, self.finder.find("YYY ZZZ <user2@example.com>"))
def test_by_profile_email(self):
- self.assertEqual(self.user1,
- self.finder.find("XXX <joeuser@awesome.com>"))
- self.assertEqual(self.user2,
- self.finder.find("YYY <john@awesome.com>"))
- self.assertEqual(self.user3,
- self.finder.find("ZZZ <bjones@awesome.com>"))
+ self.assertEqual(
+ self.user1, self.finder.find("XXX <joeuser@awesome.com>"))
+ self.assertEqual(
+ self.user2, self.finder.find("YYY <john@awesome.com>"))
+ self.assertEqual(
+ self.user3, self.finder.find("ZZZ <bjones@awesome.com>"))
def test_by_name(self):
- self.assertEqual(self.user1,
- self.finder.find("Joe User <joe@differentdomain.com>"))
- self.assertEqual(self.user1,
- self.finder.find("Joe User"))
- self.assertEqual(self.user2,
- self.finder.find("John <john@differentdomain.com>"))
- self.assertEqual(self.user2,
- self.finder.find("John"))
- self.assertEqual(self.user3,
- self.finder.find("Bob Jones <bjones AT Arch Linux DOT org>"))
+ self.assertEqual(
+ self.user1, self.finder.find("Joe User <joe@differentdomain.com>"))
+ self.assertEqual(
+ self.user1, self.finder.find("Joe User"))
+ self.assertEqual(
+ self.user2, self.finder.find("John <john@differentdomain.com>"))
+ self.assertEqual(
+ self.user2, self.finder.find("John"))
+ self.assertEqual(
+ self.user3, self.finder.find("Bob Jones <bjones AT Arch Linux DOT org>"))
def test_by_invalid(self):
- self.assertEqual(self.user1,
- self.finder.find("Joe User <user1@example.com"))
- self.assertEqual(self.user1,
- self.finder.find("Joe 'nickname' User <user1@example.com"))
- self.assertEqual(self.user1,
- self.finder.find("Joe \"nickname\" User <user1@example.com"))
- self.assertEqual(self.user1,
- self.finder.find("Joe User <joe@differentdomain.com"))
+ self.assertEqual(
+ self.user1, self.finder.find("Joe User <user1@example.com"))
+ self.assertEqual(
+ self.user1, self.finder.find("Joe 'nickname' User <user1@example.com"))
+ self.assertEqual(
+ self.user1, self.finder.find("Joe \"nickname\" User <user1@example.com"))
+ self.assertEqual(
+ self.user1, self.finder.find("Joe User <joe@differentdomain.com"))
def test_cache(self):
# simply look two of them up, but then do it repeatedly
for _ in range(5):
- self.assertEqual(self.user1,
- self.finder.find("XXX YYY <user1@example.com>"))
- self.assertEqual(self.user3,
- self.finder.find("Bob Jones <bjones AT Arch Linux DOT org>"))
+ self.assertEqual(
+ self.user1, self.finder.find("XXX YYY <user1@example.com>"))
+ self.assertEqual(
+ self.user3, self.finder.find("Bob Jones <bjones AT Arch Linux DOT org>"))
def test_ambiguous(self):
- self.assertEqual(self.user4,
- self.finder.find("Tim One <tim@anotherdomain.com>"))
- self.assertEqual(self.user5,
- self.finder.find("Tim Two <tim@anotherdomain.com>"))
+ self.assertEqual(
+ self.user4, self.finder.find("Tim One <tim@anotherdomain.com>"))
+ self.assertEqual(
+ self.user5, self.finder.find("Tim Two <tim@anotherdomain.com>"))
self.assertIsNone(self.finder.find("Tim <tim@anotherdomain.com>"))
def test_find_by_username(self):
diff --git a/devel/utils.py b/devel/utils.py
index bd57def9..715bde22 100644
--- a/devel/utils.py
+++ b/devel/utils.py
@@ -10,12 +10,13 @@ from main.utils import cache_function
from main.models import Package
from packages.models import PackageRelation
+
@cache_function(283)
def get_annotated_maintainers():
profile_ids = UserProfile.allowed_repos.through.objects.values('userprofile_id')
maintainers = User.objects.filter(
- is_active=True, userprofile__id__in=profile_ids).order_by(
- 'first_name', 'last_name')
+ is_active=True, userprofile__id__in=profile_ids).order_by(
+ 'first_name', 'last_name')
# annotate the maintainers with # of maintained and flagged packages
pkg_count_sql = """
@@ -37,7 +38,7 @@ SELECT pr.user_id, COUNT(*), COUNT(p.flag_date)
flag_count[k] = flagged
update_count = Package.objects.values_list('packager').order_by(
- 'packager').annotate(Count('packager'))
+ 'packager').annotate(Count('packager'))
update_count = dict(update_count)
for m in maintainers:
@@ -104,8 +105,7 @@ class UserFinder(object):
# ignore quoted parts; e.g. nicknames in strings
if re.match(r'^[\'"].*[\'"]$', token):
continue
- name_q &= (Q(first_name__icontains=token) |
- Q(last_name__icontains=token))
+ name_q &= (Q(first_name__icontains=token) | Q(last_name__icontains=token))
return User.objects.get(name_q)
def find(self, userstring):
@@ -132,7 +132,7 @@ class UserFinder(object):
user = None
find_methods = (self.user_email, self.profile_email,
- self.username_email, self.user_name)
+ self.username_email, self.user_name)
for matcher in find_methods:
user = matcher(name, email)
if user is not None:
@@ -179,7 +179,7 @@ class UserFinder(object):
try:
user = User.objects.get(
- userprofile__pgp_key__endswith=pgp_key)
+ userprofile__pgp_key__endswith=pgp_key)
except User.DoesNotExist:
user = None
diff --git a/devel/views.py b/devel/views.py
index 96acb720..ec07f70b 100644
--- a/devel/views.py
+++ b/devel/views.py
@@ -106,8 +106,10 @@ def stats(request):
return render(request, 'devel/stats.html', page_dict)
+
SELECTED_GROUPS = ['Developers', 'Trusted Users', 'Support Staff']
+
@login_required
def clock(request):
groups = Group.objects.filter(name__in=SELECTED_GROUPS)
@@ -247,8 +249,7 @@ def new_user_form(request):
with transaction.atomic():
form.save()
log_addition(request, form.instance.user)
- return HttpResponseRedirect('/admin/auth/user/%d/' % \
- form.instance.user.id)
+ return HttpResponseRedirect('/admin/auth/user/%d/' % form.instance.user.id)
else:
form = NewUserForm()
diff --git a/feeds.py b/feeds.py
index 99d23cfb..dd57b5a9 100644
--- a/feeds.py
+++ b/feeds.py
@@ -153,8 +153,8 @@ class PackageFeed(Feed):
# http://diveintomark.org/archives/2004/05/28/howto-atom-id
date = item.last_update
return 'tag:%s,%s:%s%s' % (Site.objects.get_current().domain,
- date.strftime('%Y-%m-%d'), item.get_absolute_url(),
- date.strftime('%Y%m%d%H%M'))
+ date.strftime('%Y-%m-%d'), item.get_absolute_url(),
+ date.strftime('%Y%m%d%H%M'))
def item_pubdate(self, item):
return item.last_update
@@ -168,6 +168,7 @@ class PackageFeed(Feed):
def item_categories(self, item):
return (item.repo.name, item.arch.name)
+
def removal_last_modified(request, *args, **kwargs):
try:
return Update.objects.latest('created').created
@@ -282,8 +283,8 @@ class PackageUpdatesFeed(Feed):
# http://diveintomark.org/archives/2004/05/28/howto-atom-id
date = item.created
return 'tag:%s,%s:%s%s' % (Site.objects.get_current().domain,
- date.strftime('%Y-%m-%d'), item.get_absolute_url(),
- date.strftime('%Y%m%d%H%M'))
+ date.strftime('%Y-%m-%d'), item.get_absolute_url(),
+ date.strftime('%Y%m%d%H%M'))
def item_pubdate(self, item):
return item.created
@@ -319,8 +320,7 @@ class NewsFeed(Feed):
__name__ = 'news_feed'
def items(self):
- return News.objects.select_related('author').order_by(
- '-postdate', '-id')[:10]
+ return News.objects.select_related('author').order_by('-postdate', '-id')[:10]
item_guid_is_permalink = False
@@ -374,7 +374,7 @@ class ReleaseFeed(Feed):
# http://diveintomark.org/archives/2004/05/28/howto-atom-id
date = item.release_date
return 'tag:%s,%s:%s' % (Site.objects.get_current().domain,
- date.strftime('%Y-%m-%d'), item.get_absolute_url())
+ date.strftime('%Y-%m-%d'), item.get_absolute_url())
def item_enclosure_url(self, item):
domain = Site.objects.get_current().domain
@@ -427,7 +427,7 @@ class PlanetFeed(Feed):
# http://diveintomark.org/archives/2004/05/28/howto-atom-id
date = item.publishdate
return 'tag:%s,%s:%s' % (Site.objects.get_current().domain,
- date.strftime('%Y-%m-%d'), item.url)
+ date.strftime('%Y-%m-%d'), item.url)
def planet_last_modified(request, *args, **kwargs):
diff --git a/local_settings.py.example b/local_settings.py.example
index f5b167f5..77d5de94 100644
--- a/local_settings.py.example
+++ b/local_settings.py.example
@@ -1,57 +1,57 @@
-## Debug settings
+# Debug settings
DEBUG = False
-#DEBUG_TOOLBAR = True
+# DEBUG_TOOLBAR = True
-## For django debug toolbar
+# For django debug toolbar
INTERNAL_IPS = ('127.0.0.1',)
-## Notification admins
+# Notification admins
ADMINS = (
- # ('Joe Admin', 'joeadmin@example.com'),
+ ('Joe Admin', 'joeadmin@example.com'),
)
-## PostgreSQL Database settings
-#DATABASES = {
-# 'default': {
-# 'ENGINE' : 'django.db.backends.postgresql',
-# 'NAME' : 'archlinux',
-# 'USER' : 'archlinux',
-# 'PASSWORD': 'archlinux',
-# 'HOST' : '',
-# 'PORT' : '',
-# },
-#}
-
-## Sqlite Database settings
+# PostgreSQL Database settings
+# DATABASES = {
+# 'default': {
+# 'ENGINE': 'django.db.backends.postgresql',
+# 'NAME': 'archlinux',
+# 'USER': 'archlinux',
+# 'PASSWORD': 'archlinux',
+# 'HOST': '',
+# 'PORT': '',
+# },
+# }
+
+# Sqlite Database settings
DATABASES = {
'default': {
- 'ENGINE' : 'django.db.backends.sqlite3',
- 'NAME' : 'database.db',
+ 'ENGINE': 'django.db.backends.sqlite3',
+ 'NAME': 'database.db',
},
}
-## Define cache settings
+# Define cache settings
CACHES = {
'default': {
- 'BACKEND' : 'django.core.cache.backends.dummy.DummyCache',
- #'BACKEND' : 'django.core.cache.backends.memcached.MemcachedCache',
- #'LOCATION': '127.0.0.1:11211',
+ 'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
+ # 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
+ # 'LOCATION': '127.0.0.1:11211',
}
}
-## Use secure session cookies? Make these True if you want all
-## logged-in actions to take place over HTTPS only. If developing
-## locally, you will want to use False.
+# Use secure session cookies? Make these True if you want all
+# logged-in actions to take place over HTTPS only. If developing
+# locally, you will want to use False.
SESSION_COOKIE_SECURE = False
CSRF_COOKIE_SECURE = False
-## location for saving dev pictures
+# location for saving dev pictures
MEDIA_ROOT = '/srv/example.com/img/'
-## web url for serving image files
+# web url for serving image files
MEDIA_URL = '/media/img/'
-## Make this unique, and don't share it with anybody.
+# Make this unique, and don't share it with anybody.
SECRET_KEY = '00000000000000000000000000000000000000000000000'
# vim: set ts=4 sw=4 et:
diff --git a/main/admin.py b/main/admin.py
index ec2b5bc8..77c94b03 100644
--- a/main/admin.py
+++ b/main/admin.py
@@ -16,15 +16,13 @@ class ArchAdmin(admin.ModelAdmin):
class RepoAdmin(admin.ModelAdmin):
- list_display = ('name', 'testing', 'staging', 'bugs_project',
- 'bugs_category', 'svn_root')
+ list_display = ('name', 'testing', 'staging', 'bugs_project', 'bugs_category', 'svn_root')
list_filter = ('testing', 'staging')
search_fields = ('name',)
class PackageAdmin(admin.ModelAdmin):
- list_display = ('pkgname', 'full_version', 'repo', 'arch', 'packager',
- 'last_update', 'build_date')
+ list_display = ('pkgname', 'full_version', 'repo', 'arch', 'packager', 'last_update', 'build_date')
list_filter = ('repo', 'arch')
search_fields = ('pkgname', 'pkgbase', 'pkgdesc')
date_hierarchy = 'build_date'
diff --git a/main/log.py b/main/log.py
index 004dbd7b..4f29f0f6 100644
--- a/main/log.py
+++ b/main/log.py
@@ -52,7 +52,7 @@ class RateLimitFilter(object):
try:
cache.set(self.prefix, 1, 300)
use_cache = (cache.get(self.prefix) == 1)
- except:
+ except: # noqa
use_cache = False
if use_cache:
diff --git a/main/management/commands/donor_import.py b/main/management/commands/donor_import.py
index 12dc0aa9..b533cd57 100644
--- a/main/management/commands/donor_import.py
+++ b/main/management/commands/donor_import.py
@@ -41,7 +41,6 @@ class Command(BaseCommand):
def add_arguments(self, parser):
parser.add_argument('maildir', type=str)
-
def decode_subject(self, subject):
subject = decode_header(subject)
default_charset = 'utf-8'
@@ -49,7 +48,6 @@ class Command(BaseCommand):
# UTF-8
return ''.join([codecs.decode(s[0], s[1] or default_charset) for s in subject])
-
def parse_subject(self, subject):
"""Format of the subject is as following: Receipt [$amount] By: John Doe [mail]"""
@@ -58,26 +56,24 @@ class Command(BaseCommand):
if parsed:
return parsed['name']
-
def sanitize_name(self, name):
- """Sanitizes the parsed name and removes numbers, entries with no
- valid characters and finally trims all excess whitespace"""
-
- # Some submissions contain no alphabetic characters, skip them
- if all(not l.isalpha() for l in name):
- return u''
+ """Sanitizes the parsed name and removes numbers, entries with no
+ valid characters and finally trims all excess whitespace"""
- # Strip any numbers, they could be a bank account number
- name = u''.join([l for l in name if not l.isdigit()])
+ # Some submissions contain no alphabetic characters, skip them
+ if all(not l.isalpha() for l in name):
+ return u''
- # Normalize all capitalized names. (JOHN DOE)
- name = u' '.join(l.capitalize() for l in name.split(u' '))
+ # Strip any numbers, they could be a bank account number
+ name = u''.join([l for l in name if not l.isdigit()])
- # Trim excess spaces
- name = name.rstrip().lstrip()
+ # Normalize all capitalized names. (JOHN DOE)
+ name = u' '.join(l.capitalize() for l in name.split(u' '))
- return name
+ # Trim excess spaces
+ name = name.rstrip().lstrip()
+ return name
def handle(self, *args, **options):
v = int(options.get('verbosity', 0))
diff --git a/main/migrations/0001_initial.py b/main/migrations/0001_initial.py
index cf9b48f6..6b6eec68 100644
--- a/main/migrations/0001_initial.py
+++ b/main/migrations/0001_initial.py
@@ -18,8 +18,10 @@ class Migration(migrations.Migration):
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('name', models.CharField(unique=True, max_length=255)),
- ('agnostic', models.BooleanField(default=False, help_text='Is this architecture non-platform specific?')),
- ('required_signoffs', models.PositiveIntegerField(default=2, help_text='Number of signoffs required for packages of this architecture')),
+ ('agnostic', models.BooleanField(
+ default=False, help_text='Is this architecture non-platform specific?')),
+ ('required_signoffs', models.PositiveIntegerField(
+ default=2, help_text='Number of signoffs required for packages of this architecture')),
],
options={
'ordering': ('name',),
@@ -33,7 +35,8 @@ class Migration(migrations.Migration):
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('name', models.CharField(unique=True, max_length=255)),
- ('visible', models.BooleanField(default=True, help_text='Should we show this donor on the public page?')),
+ ('visible', models.BooleanField(
+ default=True, help_text='Should we show this donor on the public page?')),
('created', models.DateTimeField()),
],
options={
@@ -64,8 +67,10 @@ class Migration(migrations.Migration):
('packager_str', models.CharField(max_length=255, verbose_name='packager string')),
('signature_bytes', models.BinaryField(verbose_name='PGP signature', null=True)),
('flag_date', models.DateTimeField(null=True, blank=True)),
- ('arch', models.ForeignKey(related_name='packages', on_delete=django.db.models.deletion.PROTECT, to='main.Arch')),
- ('packager', models.ForeignKey(on_delete=django.db.models.deletion.SET_NULL, blank=True, to=settings.AUTH_USER_MODEL, null=True)),
+ ('arch', models.ForeignKey(
+ related_name='packages', on_delete=django.db.models.deletion.PROTECT, to='main.Arch')),
+ ('packager', models.ForeignKey(
+ on_delete=django.db.models.deletion.SET_NULL, blank=True, to=settings.AUTH_USER_MODEL, null=True)),
],
options={
'ordering': ('pkgname',),
@@ -95,9 +100,12 @@ class Migration(migrations.Migration):
('name', models.CharField(unique=True, max_length=255)),
('testing', models.BooleanField(default=False, help_text='Is this repo meant for package testing?')),
('staging', models.BooleanField(default=False, help_text='Is this repo meant for package staging?')),
- ('bugs_project', models.SmallIntegerField(default=1, help_text='Flyspray project ID for this repository.')),
- ('bugs_category', models.SmallIntegerField(default=2, help_text='Flyspray category ID for this repository.')),
- ('svn_root', models.CharField(help_text='SVN root (e.g. path) for this repository.', max_length=64)),
+ ('bugs_project', models.SmallIntegerField(
+ default=1, help_text='Flyspray project ID for this repository.')),
+ ('bugs_category', models.SmallIntegerField(
+ default=2, help_text='Flyspray category ID for this repository.')),
+ ('svn_root', models.CharField(
+ help_text='SVN root (e.g. path) for this repository.', max_length=64)),
],
options={
'ordering': ('name',),
@@ -108,7 +116,10 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='package',
name='repo',
- field=models.ForeignKey(related_name='packages', on_delete=django.db.models.deletion.PROTECT, to='main.Repo'),
+ field=models.ForeignKey(
+ related_name='packages',
+ on_delete=django.db.models.deletion.PROTECT,
+ to='main.Repo'),
preserve_default=True,
),
migrations.AlterUniqueTogether(
diff --git a/main/migrations/0002_repo_public_testing.py b/main/migrations/0002_repo_public_testing.py
index 3f87234e..fc9f0f97 100644
--- a/main/migrations/0002_repo_public_testing.py
+++ b/main/migrations/0002_repo_public_testing.py
@@ -13,6 +13,7 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='repo',
name='public_testing',
- field=models.BooleanField(default=False, help_text='Is this repo meant for package testing (without signoffs)?'),
+ field=models.BooleanField(
+ default=False, help_text='Is this repo meant for package testing (without signoffs)?'),
),
]
diff --git a/main/models.py b/main/models.py
index f80786af..086a26ca 100644
--- a/main/models.py
+++ b/main/models.py
@@ -28,8 +28,8 @@ class PackageManager(models.Manager):
class Donor(models.Model):
name = models.CharField(max_length=255, unique=True)
- visible = models.BooleanField(default=True,
- help_text="Should we show this donor on the public page?")
+ visible = models.BooleanField(
+ default=True, help_text="Should we show this donor on the public page?")
created = models.DateTimeField()
def __str__(self):
@@ -43,10 +43,10 @@ class Donor(models.Model):
class Arch(models.Model):
name = models.CharField(max_length=255, unique=True)
- agnostic = models.BooleanField(default=False,
- help_text="Is this architecture non-platform specific?")
- required_signoffs = models.PositiveIntegerField(default=2,
- help_text="Number of signoffs required for packages of this architecture")
+ agnostic = models.BooleanField(
+ default=False, help_text="Is this architecture non-platform specific?")
+ required_signoffs = models.PositiveIntegerField(
+ default=2, help_text="Number of signoffs required for packages of this architecture")
def __str__(self):
return self.name
@@ -62,18 +62,18 @@ class Arch(models.Model):
class Repo(models.Model):
name = models.CharField(max_length=255, unique=True)
- testing = models.BooleanField(default=False,
- help_text="Is this repo meant for package testing?")
- public_testing = models.BooleanField(default=False,
- help_text="Is this repo meant for package testing (without signoffs)?")
- staging = models.BooleanField(default=False,
- help_text="Is this repo meant for package staging?")
- bugs_project = models.SmallIntegerField(default=1,
- help_text="Flyspray project ID for this repository.")
- bugs_category = models.SmallIntegerField(default=2,
- help_text="Flyspray category ID for this repository.")
- svn_root = models.CharField(max_length=64,
- help_text="SVN root (e.g. path) for this repository.")
+ testing = models.BooleanField(
+ default=False, help_text="Is this repo meant for package testing?")
+ public_testing = models.BooleanField(
+ default=False, help_text="Is this repo meant for package testing (without signoffs)?")
+ staging = models.BooleanField(
+ default=False, help_text="Is this repo meant for package staging?")
+ bugs_project = models.SmallIntegerField(
+ default=1, help_text="Flyspray project ID for this repository.")
+ bugs_category = models.SmallIntegerField(
+ default=2, help_text="Flyspray category ID for this repository.")
+ svn_root = models.CharField(
+ max_length=64, help_text="SVN root (e.g. path) for this repository.")
def __str__(self):
return self.name
@@ -87,10 +87,8 @@ class Repo(models.Model):
class Package(models.Model):
- repo = models.ForeignKey(Repo, related_name="packages",
- on_delete=models.PROTECT)
- arch = models.ForeignKey(Arch, related_name="packages",
- on_delete=models.PROTECT)
+ repo = models.ForeignKey(Repo, related_name="packages", on_delete=models.PROTECT)
+ arch = models.ForeignKey(Arch, related_name="packages", on_delete=models.PROTECT)
pkgname = models.CharField(max_length=255)
pkgbase = models.CharField(max_length=255, db_index=True)
pkgver = models.CharField(max_length=255)
@@ -106,8 +104,7 @@ class Package(models.Model):
files_last_update = models.DateTimeField(null=True, blank=True)
created = models.DateTimeField()
packager_str = models.CharField('packager string', max_length=255)
- packager = models.ForeignKey(User, null=True, blank=True,
- on_delete=models.SET_NULL)
+ packager = models.ForeignKey(User, null=True, blank=True, on_delete=models.SET_NULL)
signature_bytes = models.BinaryField('PGP signature', null=True)
flag_date = models.DateTimeField(null=True, blank=True)
@@ -129,13 +126,12 @@ class Package(models.Model):
return '%s-%s' % (self.pkgver, self.pkgrel)
def get_absolute_url(self):
- return '/packages/%s/%s/%s/' % (self.repo.name.lower(),
- self.arch.name, self.pkgname)
+ return f'/packages/{self.repo.name.lower()}/{self.arch.name}/{self.pkgname}/'
def get_full_url(self, proto='https'):
'''get a URL suitable for things like email including the domain'''
domain = Site.objects.get_current().domain
- return '%s://%s%s' % (proto, domain, self.get_absolute_url())
+ return f'{proto}://{domain}{self.get_absolute_url()}'
@property
def signature(self):
@@ -151,7 +147,7 @@ class Package(models.Model):
if sig and sig.key_id:
try:
matching_key = DeveloperKey.objects.select_related(
- 'owner').get(key=sig.key_id, owner_id__isnull=False)
+ 'owner').get(key=sig.key_id, owner_id__isnull=False)
user = matching_key.owner
except DeveloperKey.DoesNotExist:
user = None
@@ -165,8 +161,8 @@ class Package(models.Model):
from packages.models import PackageRelation
if self._maintainers is None:
self._maintainers = User.objects.filter(
- package_relations__pkgbase=self.pkgbase,
- package_relations__type=PackageRelation.MAINTAINER)
+ package_relations__pkgbase=self.pkgbase,
+ package_relations__type=PackageRelation.MAINTAINER)
return self._maintainers
@maintainers.setter
@@ -200,16 +196,16 @@ class Package(models.Model):
SELECT %s UNION ALL
SELECT z.name FROM packages_provision z WHERE z.pkg_id = %s
)'''
- requiredby = Depend.objects.select_related('pkg',
- 'pkg__arch', 'pkg__repo').extra(
- select={'sorttype': sorttype},
- where=[name_clause], params=[self.pkgname, self.id]).order_by(
- 'sorttype', 'pkg__pkgname',
- 'pkg__arch__name', 'pkg__repo__name')
+ requiredby = Depend.objects.select_related(
+ 'pkg', 'pkg__arch', 'pkg__repo').extra(
+ select={'sorttype': sorttype},
+ where=[name_clause], params=[self.pkgname, self.id]).order_by(
+ 'sorttype', 'pkg__pkgname',
+ 'pkg__arch__name', 'pkg__repo__name')
if not self.arch.agnostic:
# make sure we match architectures if possible
requiredby = requiredby.filter(
- pkg__arch__in=self.applicable_arches())
+ pkg__arch__in=self.applicable_arches())
# if we can use ALPM, ensure our returned Depend objects abide by the
# version comparison operators they may specify
@@ -223,22 +219,19 @@ class Package(models.Model):
new_rqd.append(dep)
elif self.pkgname == dep.name:
# depends on this package, so check it directly
- if alpm.compare_versions(self.full_version,
- dep.comparison, dep.version):
+ if alpm.compare_versions(self.full_version, dep.comparison, dep.version):
new_rqd.append(dep)
else:
# it must be a provision of ours at this point
for provide in (p for p in provides if p.name == dep.name):
- if alpm.compare_versions(provide.version,
- dep.comparison, dep.version):
+ if alpm.compare_versions(provide.version, dep.comparison, dep.version):
new_rqd.append(dep)
break
requiredby = new_rqd
# sort out duplicate packages; this happens if something has a double
# versioned depend such as a kernel module
- requiredby = [list(vals)[0] for _, vals in
- groupby(requiredby, lambda x: x.pkg.id)]
+ requiredby = [list(vals)[0] for _, vals in groupby(requiredby, lambda x: x.pkg.id)]
if not requiredby:
return requiredby
@@ -258,11 +251,9 @@ class Package(models.Model):
# find another package by this name in a different testing or staging
# repo; if we can't, we can short-circuit some checks
- repo_q = (Q(repo__testing=(not self.repo.testing)) |
- Q(repo__staging=(not self.repo.staging)))
+ repo_q = (Q(repo__testing=(not self.repo.testing)) | Q(repo__staging=(not self.repo.staging)))
if not Package.objects.filter(
- repo_q, pkgname=self.pkgname, arch=self.arch
- ).exclude(id=self.id).exists():
+ repo_q, pkgname=self.pkgname, arch=self.arch).exclude(id=self.id).exists():
# there isn't one? short circuit, all required by entries are fine
return filtered
@@ -274,9 +265,8 @@ class Package(models.Model):
dep_pkgs = list(dep_pkgs)
dep = dep_pkgs[0]
if len(dep_pkgs) > 1:
- dep_pkgs = [d for d in dep_pkgs
- if d.pkg.repo.testing == self.repo.testing and
- d.pkg.repo.staging == self.repo.staging]
+ dep_pkgs = [d for d in dep_pkgs if d.pkg.repo.testing == self.repo.testing
+ and d.pkg.repo.staging == self.repo.staging]
if len(dep_pkgs) > 0:
dep = dep_pkgs[0]
trimmed.append(dep)
@@ -331,8 +321,8 @@ class Package(models.Model):
if conflict.name != self.pkgname:
continue
if not conflict.comparison or not conflict.version \
- or alpm.compare_versions(self.full_version,
- conflict.comparison, conflict.version):
+ or alpm.compare_versions(
+ self.full_version, conflict.comparison, conflict.version):
new_pkgs.append(package)
return new_pkgs
@@ -344,14 +334,14 @@ class Package(models.Model):
"""
try:
# start by looking for something in this repo
- return Package.objects.normal().get(arch=self.arch,
- repo=self.repo, pkgname=self.pkgbase)
+ return Package.objects.normal().get(
+ arch=self.arch, repo=self.repo, pkgname=self.pkgbase)
except Package.DoesNotExist:
# this package might be split across repos? find one
# that matches the correct [testing] repo flag
- pkglist = Package.objects.normal().filter(arch=self.arch,
- repo__testing=self.repo.testing,
- repo__staging=self.repo.staging, pkgname=self.pkgbase)
+ pkglist = Package.objects.normal().filter(
+ arch=self.arch, repo__testing=self.repo.testing,
+ repo__staging=self.repo.staging, pkgname=self.pkgbase)
if len(pkglist) > 0:
return pkglist[0]
return None
@@ -365,10 +355,10 @@ class Package(models.Model):
return value will be an empty list.
"""
return Package.objects.normal().filter(
- arch__in=self.applicable_arches(),
- repo__testing=self.repo.testing,
- repo__staging=self.repo.staging,
- pkgbase=self.pkgbase).exclude(id=self.id)
+ arch__in=self.applicable_arches(),
+ repo__testing=self.repo.testing,
+ repo__staging=self.repo.staging,
+ pkgbase=self.pkgbase).exclude(id=self.id)
def flag_request(self):
if self.flag_date is None:
@@ -378,9 +368,9 @@ class Package(models.Model):
# Note that we don't match on pkgrel here; this is because a pkgrel
# bump does not unflag a package so we can still show the same flag
# request from a different pkgrel.
- request = FlagRequest.objects.filter(pkgbase=self.pkgbase,
- repo=self.repo, pkgver=self.pkgver,
- epoch=self.epoch, is_spam=False).latest()
+ request = FlagRequest.objects.filter(
+ pkgbase=self.pkgbase, repo=self.repo,
+ pkgver=self.pkgver, epoch=self.epoch, is_spam=False).latest()
return request
except FlagRequest.DoesNotExist:
return None
@@ -388,9 +378,9 @@ class Package(models.Model):
def is_same_version(self, other):
'is this package similar, name and version-wise, to another'
return self.pkgname == other.pkgname \
- and self.pkgver == other.pkgver \
- and self.pkgrel == other.pkgrel \
- and self.epoch == other.epoch
+ and self.pkgver == other.pkgver \
+ and self.pkgrel == other.pkgrel \
+ and self.epoch == other.epoch
def in_testing(self):
'''attempt to locate this package in a testing repo; if we are in
@@ -398,8 +388,8 @@ class Package(models.Model):
if self.repo.testing:
return None
try:
- return Package.objects.normal().get(repo__testing=True,
- pkgname=self.pkgname, arch=self.arch)
+ return Package.objects.normal().get(
+ repo__testing=True, pkgname=self.pkgname, arch=self.arch)
except Package.DoesNotExist:
return None
@@ -409,8 +399,8 @@ class Package(models.Model):
if self.repo.staging:
return None
try:
- return Package.objects.normal().get(repo__staging=True,
- pkgname=self.pkgname, arch=self.arch)
+ return Package.objects.normal().get(
+ repo__staging=True, pkgname=self.pkgname, arch=self.arch)
except Package.DoesNotExist:
return None
@@ -426,8 +416,8 @@ class Package(models.Model):
names.append('lib32-' + self.pkgname)
names.append(self.pkgname + '-multilib')
return Package.objects.normal().filter(
- pkgname__in=names).exclude(id=self.id).order_by(
- 'arch__name', 'repo__name')
+ pkgname__in=names).exclude(id=self.id).order_by(
+ 'arch__name', 'repo__name')
class PackageFile(models.Model):
@@ -478,11 +468,10 @@ class RebuilderdStatus(models.Model):
return "pkg=%s, status=%s" % (self.pkg, self.status_str)
-from django.db.models.signals import pre_save
+from django.db.models.signals import pre_save # noqa
# note: reporead sets the 'created' field on Package objects, so no signal
# listener is set up here to do so
-pre_save.connect(set_created_field, sender=Donor,
- dispatch_uid="main.models")
+pre_save.connect(set_created_field, sender=Donor, dispatch_uid="main.models")
# vim: set ts=4 sw=4 et:
diff --git a/main/templatetags/attributes.py b/main/templatetags/attributes.py
index ab09b63e..a6be4b50 100644
--- a/main/templatetags/attributes.py
+++ b/main/templatetags/attributes.py
@@ -2,9 +2,10 @@ import re
from django import template
from django.conf import settings
-numeric_test = re.compile("^\d+$")
+numeric_test = re.compile(r"^\d+$")
register = template.Library()
+
def attribute(value, arg):
"""Gets an attribute of an object dynamically from a string name"""
if hasattr(value, str(arg)):
@@ -16,6 +17,7 @@ def attribute(value, arg):
else:
return settings.TEMPLATE_STRING_IF_INVALID
+
register.filter('attribute', attribute)
# vim: set ts=4 sw=4 et:
diff --git a/main/templatetags/cdn.py b/main/templatetags/cdn.py
index 2be23607..035c95a3 100644
--- a/main/templatetags/cdn.py
+++ b/main/templatetags/cdn.py
@@ -21,6 +21,7 @@ def jquery_tablesorter():
link = staticfiles_storage.url(filename)
return format_html('<script type="text/javascript" src="%s"></script>' % link)
+
@register.simple_tag
def d3js():
version = '3.5.0'
diff --git a/main/templatetags/flags.py b/main/templatetags/flags.py
index d47ee707..54115d35 100644
--- a/main/templatetags/flags.py
+++ b/main/templatetags/flags.py
@@ -9,7 +9,7 @@ def country_flag(country):
if not country:
return ''
return format_html('<span class="fam-flag fam-flag-%s" title="%s"></span> ' % (
- str(country.code).lower(), str(country.name)))
+ str(country.code).lower(), str(country.name)))
# vim: set ts=4 sw=4 et:
diff --git a/main/templatetags/pgp.py b/main/templatetags/pgp.py
index 4597e10b..686c7da1 100644
--- a/main/templatetags/pgp.py
+++ b/main/templatetags/pgp.py
@@ -13,10 +13,11 @@ def format_key(key_id):
elif len(key_id) == 40:
# normal display format is 5 groups of 4 hex chars seperated by spaces,
# double space, then 5 more groups of 4 hex chars
- split = tuple(key_id[i:i+4] for i in range(0, 40, 4))
+ split = tuple(key_id[i:i + 4] for i in range(0, 40, 4))
return '%s\u00a0 %s' % (' '.join(split[0:5]), ' '.join(split[5:10]))
return '0x%s' % key_id
+
@register.simple_tag
def pgp_key_link(key_id, link_text=None):
if not key_id:
@@ -36,8 +37,7 @@ def pgp_key_link(key_id, link_text=None):
return format_key(key_id)
pgp_server_secure = getattr(settings, 'PGP_SERVER_SECURE', False)
scheme = 'https' if pgp_server_secure else 'http'
- url = '%s://%s/pks/lookup?op=vindex&amp;fingerprint=on&amp;exact=on&amp;search=0x%s' % \
- (scheme, pgp_server, key_id)
+ url = '%s://%s/pks/lookup?op=vindex&amp;fingerprint=on&amp;exact=on&amp;search=0x%s' % (scheme, pgp_server, key_id)
if link_text is None:
link_text = '0x%s' % key_id[-8:]
values = (url, format_key(key_id), link_text)
diff --git a/main/tests/test_donor_import.py b/main/tests/test_donor_import.py
index 0f27eee7..33fcad1f 100644
--- a/main/tests/test_donor_import.py
+++ b/main/tests/test_donor_import.py
@@ -19,9 +19,6 @@ class DonorImportTest(TransactionTestCase):
def setUp(self):
self.command = Command()
- def gen_parse_subject(self, data):
- return self.command.parse_subject(valid.format(data))
-
def test_parse_subject(self):
self.assertIsNone(self.command.parse_subject('garbage'))
diff --git a/main/tests/test_templatetags_pgp.py b/main/tests/test_templatetags_pgp.py
index 39ace88b..3a55ff1a 100644
--- a/main/tests/test_templatetags_pgp.py
+++ b/main/tests/test_templatetags_pgp.py
@@ -6,7 +6,6 @@ from main.templatetags.pgp import pgp_key_link, format_key, pgp_fingerprint
class PGPTemplateTest(TestCase):
-
def test_format_key(self):
# 40 len case
pgp_key = '423423fD9004FB063E2C81117BFB1108D234DAFZ'
diff --git a/main/utils.py b/main/utils.py
index 57026616..2fb1ea76 100644
--- a/main/utils.py
+++ b/main/utils.py
@@ -146,8 +146,7 @@ class PackageStandin(object):
return getattr(self.package, name)
def get_absolute_url(self):
- return '/packages/%s/%s/%s/' % (
- self.repo.name.lower(), self.arch.name, self.pkgbase)
+ return f'/packages/{self.repo.name.lower()}/{self.arch.name}/{self.pkgname}/'
class DependStandin(object):
diff --git a/mirrors/admin.py b/mirrors/admin.py
index 8cfb3d05..b542e97b 100644
--- a/mirrors/admin.py
+++ b/mirrors/admin.py
@@ -5,7 +5,7 @@ from django import forms
from django.contrib import admin
from .models import (Mirror, MirrorProtocol, MirrorUrl, MirrorRsync,
- CheckLocation)
+ CheckLocation)
class MirrorUrlForm(forms.ModelForm):
@@ -54,24 +54,24 @@ class MirrorAdminForm(forms.ModelForm):
class Meta:
model = Mirror
fields = ('name', 'tier', 'upstream', 'admin_email', 'alternate_email',
- 'public', 'active', 'isos', 'rsync_user', 'rsync_password',
- 'bug', 'notes')
+ 'public', 'active', 'isos', 'rsync_user', 'rsync_password',
+ 'bug', 'notes')
upstream = forms.ModelChoiceField(
- queryset=Mirror.objects.filter(tier__gte=0, tier__lte=1),
- required=False)
+ queryset=Mirror.objects.filter(tier__gte=0, tier__lte=1),
+ required=False)
class MirrorAdmin(admin.ModelAdmin):
form = MirrorAdminForm
list_display = ('name', 'tier', 'active', 'public',
- 'isos', 'admin_email', 'alternate_email')
+ 'isos', 'admin_email', 'alternate_email')
list_filter = ('tier', 'active', 'public')
search_fields = ('name', 'admin_email', 'alternate_email')
readonly_fields = ('created', 'last_modified')
inlines = [
- MirrorUrlInlineAdmin,
- MirrorRsyncInlineAdmin,
+ MirrorUrlInlineAdmin,
+ MirrorRsyncInlineAdmin,
]
def save_model(self, request, obj, form, change):
diff --git a/mirrors/management/commands/mirrorcheck.py b/mirrors/management/commands/mirrorcheck.py
index 70429b71..79772523 100644
--- a/mirrors/management/commands/mirrorcheck.py
+++ b/mirrors/management/commands/mirrorcheck.py
@@ -70,7 +70,7 @@ class Command(BaseCommand):
timeout = options.get('timeout')
urls = MirrorUrl.objects.select_related('protocol').filter(
- active=True, mirror__active=True, mirror__public=True)
+ active=True, mirror__active=True, mirror__public=True)
location = options.get('location', None)
if location:
@@ -183,8 +183,7 @@ def check_rsync_url(mirror_url, location, timeout):
elif location.family == socket.AF_INET:
ipopt = '--ipv4'
lastsync_path = os.path.join(tempdir, 'lastsync')
- rsync_cmd = ["rsync", "--quiet", "--contimeout=%d" % timeout,
- "--timeout=%d" % timeout]
+ rsync_cmd = ["rsync", "--quiet", "--contimeout=%d" % timeout, "--timeout=%d" % timeout]
if ipopt:
rsync_cmd.append(ipopt)
rsync_cmd.append(url)
@@ -194,8 +193,7 @@ def check_rsync_url(mirror_url, location, timeout):
if logger.isEnabledFor(logging.DEBUG):
logger.debug("rsync cmd: %s", ' '.join(rsync_cmd))
start = time.time()
- proc = subprocess.Popen(rsync_cmd, stdout=devnull,
- stderr=subprocess.PIPE)
+ proc = subprocess.Popen(rsync_cmd, stdout=devnull, stderr=subprocess.PIPE)
_, errdata = proc.communicate()
end = time.time()
log.duration = end - start
@@ -229,8 +227,7 @@ def mirror_url_worker(work, output, location, timeout):
try:
if url.protocol.protocol == 'rsync':
log = check_rsync_url(url, location, timeout)
- elif (url.protocol.protocol == 'ftp' and location and
- location.family == socket.AF_INET6):
+ elif (url.protocol.protocol == 'ftp' and location and location.family == socket.AF_INET6):
# IPv6 + FTP don't work; skip checking completely
log = None
else:
@@ -251,8 +248,7 @@ class MirrorCheckPool(object):
self.tasks.put(url)
self.threads = []
for _ in range(num_threads):
- thread = Thread(target=mirror_url_worker,
- args=(self.tasks, self.logs, location, timeout))
+ thread = Thread(target=mirror_url_worker, args=(self.tasks, self.logs, location, timeout))
thread.daemon = True
self.threads.append(thread)
diff --git a/mirrors/management/commands/mirrorresolv.py b/mirrors/management/commands/mirrorresolv.py
index d3d8d5f6..e2981476 100644
--- a/mirrors/management/commands/mirrorresolv.py
+++ b/mirrors/management/commands/mirrorresolv.py
@@ -23,6 +23,7 @@ logging.basicConfig(
stream=sys.stderr)
logger = logging.getLogger()
+
class Command(BaseCommand):
help = "Runs a check on all active mirror URLs to determine if they are reachable via IPv4 and/or v6."
@@ -37,6 +38,7 @@ class Command(BaseCommand):
return resolve_mirrors()
+
def resolve_mirrors():
logger.debug("requesting list of mirror URLs")
for mirrorurl in MirrorUrl.objects.filter(active=True, mirror__active=True):
@@ -48,7 +50,7 @@ def resolve_mirrors():
mirrorurl.has_ipv4 = socket.AF_INET in families
mirrorurl.has_ipv6 = socket.AF_INET6 in families
logger.debug("%s: v4: %s v6: %s", mirrorurl.hostname,
- mirrorurl.has_ipv4, mirrorurl.has_ipv6)
+ mirrorurl.has_ipv4, mirrorurl.has_ipv6)
# now check new values, only update if new != old
newvals = (mirrorurl.has_ipv4, mirrorurl.has_ipv6)
if newvals != oldvals:
diff --git a/mirrors/migrations/0001_squashed_0002_mirrorurl_bandwidth.py b/mirrors/migrations/0001_squashed_0002_mirrorurl_bandwidth.py
index 1818287c..9cfc439b 100644
--- a/mirrors/migrations/0001_squashed_0002_mirrorurl_bandwidth.py
+++ b/mirrors/migrations/0001_squashed_0002_mirrorurl_bandwidth.py
@@ -34,7 +34,8 @@ class Migration(migrations.Migration):
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255, unique=True)),
- ('tier', models.SmallIntegerField(choices=[(0, 'Tier 0'), (1, 'Tier 1'), (2, 'Tier 2'), (-1, 'Untiered')], default=2)),
+ ('tier', models.SmallIntegerField(
+ choices=[(0, 'Tier 0'), (1, 'Tier 1'), (2, 'Tier 2'), (-1, 'Untiered')], default=2)),
('admin_email', models.EmailField(blank=True, max_length=255)),
('alternate_email', models.EmailField(blank=True, max_length=255)),
('public', models.BooleanField(default=True)),
@@ -46,7 +47,8 @@ class Migration(migrations.Migration):
('notes', models.TextField(blank=True)),
('created', models.DateTimeField(editable=False)),
('last_modified', models.DateTimeField(editable=False)),
- ('upstream', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='mirrors.Mirror')),
+ ('upstream', models.ForeignKey(
+ null=True, on_delete=django.db.models.deletion.SET_NULL, to='mirrors.Mirror')),
],
options={
'ordering': ('name',),
@@ -61,7 +63,9 @@ class Migration(migrations.Migration):
('duration', models.FloatField(null=True)),
('is_success', models.BooleanField(default=True)),
('error', models.TextField(blank=True, default='')),
- ('location', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='logs', to='mirrors.CheckLocation')),
+ ('location', models.ForeignKey(
+ null=True, on_delete=django.db.models.deletion.CASCADE,
+ related_name='logs', to='mirrors.CheckLocation')),
],
options={
'get_latest_by': 'check_time',
@@ -73,8 +77,10 @@ class Migration(migrations.Migration):
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('protocol', models.CharField(max_length=10, unique=True)),
- ('is_download', models.BooleanField(default=True, help_text='Is protocol useful for end-users, e.g. HTTP')),
- ('default', models.BooleanField(default=True, help_text='Included by default when building mirror list?')),
+ ('is_download', models.BooleanField(
+ default=True, help_text='Is protocol useful for end-users, e.g. HTTP')),
+ ('default', models.BooleanField(
+ default=True, help_text='Included by default when building mirror list?')),
('created', models.DateTimeField(editable=False)),
],
options={
@@ -87,7 +93,9 @@ class Migration(migrations.Migration):
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('ip', mirrors.fields.IPNetworkField(max_length=44, verbose_name='IP')),
('created', models.DateTimeField(editable=False)),
- ('mirror', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='rsync_ips', to='mirrors.Mirror')),
+ ('mirror', models.ForeignKey(
+ on_delete=django.db.models.deletion.CASCADE,
+ related_name='rsync_ips', to='mirrors.Mirror')),
],
options={
'ordering': ('ip',),
@@ -104,8 +112,12 @@ class Migration(migrations.Migration):
('has_ipv6', models.BooleanField(default=False, editable=False, verbose_name='IPv6 capable')),
('created', models.DateTimeField(editable=False)),
('active', models.BooleanField(default=True)),
- ('mirror', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='urls', to='mirrors.Mirror')),
- ('protocol', models.ForeignKey(editable=False, on_delete=django.db.models.deletion.PROTECT, related_name='urls', to='mirrors.MirrorProtocol')),
+ ('mirror', models.ForeignKey(
+ on_delete=django.db.models.deletion.CASCADE,
+ related_name='urls', to='mirrors.Mirror')),
+ ('protocol', models.ForeignKey(
+ editable=False, on_delete=django.db.models.deletion.PROTECT,
+ related_name='urls', to='mirrors.MirrorProtocol')),
('bandwidth', models.FloatField(blank=True, null=True, verbose_name='bandwidth (mbits)')),
],
options={
@@ -115,6 +127,8 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='mirrorlog',
name='url',
- field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='logs', to='mirrors.MirrorUrl'),
+ field=models.ForeignKey(
+ on_delete=django.db.models.deletion.CASCADE,
+ related_name='logs', to='mirrors.MirrorUrl'),
),
]
diff --git a/mirrors/models.py b/mirrors/models.py
index f6e70d99..17ac02df 100644
--- a/mirrors/models.py
+++ b/mirrors/models.py
@@ -54,10 +54,10 @@ class Mirror(models.Model):
class MirrorProtocol(models.Model):
protocol = models.CharField(max_length=10, unique=True)
- is_download = models.BooleanField(default=True,
- help_text="Is protocol useful for end-users, e.g. HTTP")
- default = models.BooleanField(default=True,
- help_text="Included by default when building mirror list?")
+ is_download = models.BooleanField(
+ default=True, help_text="Is protocol useful for end-users, e.g. HTTP")
+ default = models.BooleanField(
+ default=True, help_text="Included by default when building mirror list?")
created = models.DateTimeField(editable=False)
def __str__(self):
@@ -69,14 +69,13 @@ class MirrorProtocol(models.Model):
class MirrorUrl(models.Model):
url = models.CharField("URL", max_length=255, unique=True)
- protocol = models.ForeignKey(MirrorProtocol, related_name="urls",
- editable=False, on_delete=models.PROTECT)
+ protocol = models.ForeignKey(
+ MirrorProtocol, related_name="urls",
+ editable=False, on_delete=models.PROTECT)
mirror = models.ForeignKey(Mirror, related_name="urls", on_delete=models.CASCADE)
country = CountryField(blank=True, db_index=True)
- has_ipv4 = models.BooleanField("IPv4 capable", default=True,
- editable=False)
- has_ipv6 = models.BooleanField("IPv6 capable", default=False,
- editable=False)
+ has_ipv4 = models.BooleanField("IPv4 capable", default=True, editable=False)
+ has_ipv6 = models.BooleanField("IPv6 capable", default=False, editable=False)
active = models.BooleanField(default=True)
bandwidth = models.FloatField("bandwidth (mbits)", null=True, blank=True)
created = models.DateTimeField(editable=False)
@@ -137,8 +136,8 @@ class MirrorRsync(models.Model):
class CheckLocation(models.Model):
hostname = models.CharField(max_length=255)
- source_ip = models.GenericIPAddressField('source IP',
- unpack_ipv4=True, unique=True)
+ source_ip = models.GenericIPAddressField(
+ 'source IP', unpack_ipv4=True, unique=True)
country = CountryField()
created = models.DateTimeField(editable=False)
@@ -191,7 +190,6 @@ class MirrorLog(models.Model):
for model in (Mirror, MirrorProtocol, MirrorUrl, MirrorRsync, CheckLocation):
- pre_save.connect(set_created_field, sender=model,
- dispatch_uid="mirrors.models")
+ pre_save.connect(set_created_field, sender=model, dispatch_uid="mirrors.models")
# vim: set ts=4 sw=4 et:
diff --git a/mirrors/templatetags/mirror_status.py b/mirrors/templatetags/mirror_status.py
index 83c1571a..26d7ebac 100644
--- a/mirrors/templatetags/mirror_status.py
+++ b/mirrors/templatetags/mirror_status.py
@@ -3,6 +3,7 @@ from django import template
register = template.Library()
+
@register.filter
def duration(value):
if not value and type(value) != timedelta:
@@ -13,6 +14,7 @@ def duration(value):
hrs, mins = divmod(mins, 60)
return '%d:%02d' % (hrs, mins)
+
@register.filter
def hours(value):
if not value and type(value) != timedelta:
diff --git a/mirrors/tests/__init__.py b/mirrors/tests/__init__.py
index 4ea5e1fb..cd239adb 100644
--- a/mirrors/tests/__init__.py
+++ b/mirrors/tests/__init__.py
@@ -3,11 +3,11 @@ from mirrors.models import MirrorUrl, MirrorProtocol, Mirror
def create_mirror_url(name='mirror1', country='US',
protocol='http', url='https://archlinux.org/'):
- mirror = Mirror.objects.create(name=name,
- admin_email='admin@archlinux.org')
- mirror_protocol = MirrorProtocol.objects.create(protocol=protocol)
- mirror_url = MirrorUrl.objects.create(url=url,
- protocol=mirror_protocol,
- mirror=mirror,
- country=country)
- return mirror_url
+ mirror = Mirror.objects.create(name=name,
+ admin_email='admin@archlinux.org')
+ mirror_protocol = MirrorProtocol.objects.create(protocol=protocol)
+ mirror_url = MirrorUrl.objects.create(url=url,
+ protocol=mirror_protocol,
+ mirror=mirror,
+ country=country)
+ return mirror_url
diff --git a/mirrors/tests/test_mirrorcheck.py b/mirrors/tests/test_mirrorcheck.py
index c4a6450d..611cd115 100644
--- a/mirrors/tests/test_mirrorcheck.py
+++ b/mirrors/tests/test_mirrorcheck.py
@@ -147,7 +147,7 @@ class MirrorCheckTest(TestCase):
def test_checklocation_model(self):
checkloc = CheckLocation.objects.create(hostname='archlinux.org',
- source_ip='1.1.1.1')
+ source_ip='1.1.1.1')
with mock.patch('mirrors.management.commands.mirrorcheck.logger') as logger:
call_command('mirrorcheck', '-l', '1')
logger.info.assert_called()
diff --git a/mirrors/tests/test_mirrorrsync.py b/mirrors/tests/test_mirrorrsync.py
index 31dc325d..bf5d26fd 100644
--- a/mirrors/tests/test_mirrorrsync.py
+++ b/mirrors/tests/test_mirrorrsync.py
@@ -6,6 +6,7 @@ from mirrors.models import MirrorRsync, Mirror
TEST_IPV6 = "2a0b:4342:1a31:410::"
TEST_IPV4 = "8.8.8.8"
+
class MirrorRsyncTest(TransactionTestCase):
def setUp(self):
self.mirror = Mirror.objects.create(name='rmirror',
diff --git a/mirrors/tests/test_templatetags.py b/mirrors/tests/test_templatetags.py
index ec9b61bd..157329f8 100644
--- a/mirrors/tests/test_templatetags.py
+++ b/mirrors/tests/test_templatetags.py
@@ -19,7 +19,7 @@ class MirrorTemplateTagTest(SimpleTestCase):
self.assertEqual(hours(timedelta(hours=5)), '5 hours')
self.assertEqual(hours(timedelta(hours=1)), '1 hour')
- self.assertEqual(hours(timedelta(seconds=60*60)), '1 hour')
+ self.assertEqual(hours(timedelta(seconds=60 * 60)), '1 hour')
def test_percentage(self):
self.assertEqual(percentage(None), u'')
diff --git a/mirrors/utils.py b/mirrors/utils.py
index bf0af23f..78538fb6 100644
--- a/mirrors/utils.py
+++ b/mirrors/utils.py
@@ -20,6 +20,7 @@ def dictfetchall(cursor):
for row in cursor.fetchall()
]
+
def status_data(cutoff_time, mirror_id=None):
if mirror_id is not None:
params = [cutoff_time, mirror_id]
@@ -117,12 +118,11 @@ def get_mirror_statuses(cutoff=DEFAULT_CUTOFF, mirror_id=None, show_all=False):
cutoff_time = now() - cutoff
urls = MirrorUrl.objects.select_related(
- 'mirror', 'protocol').order_by('mirror__id', 'url')
+ 'mirror', 'protocol').order_by('mirror__id', 'url')
if mirror_id:
urls = urls.filter(mirror_id=mirror_id)
if not show_all:
- urls = urls.filter(active=True, mirror__active=True,
- mirror__public=True)
+ urls = urls.filter(active=True, mirror__active=True, mirror__public=True)
if urls:
url_data = status_data(cutoff_time, mirror_id)
@@ -133,10 +133,10 @@ def get_mirror_statuses(cutoff=DEFAULT_CUTOFF, mirror_id=None, show_all=False):
if mirror_id:
check_info = check_info.filter(url__mirror_id=mirror_id)
check_info = check_info.aggregate(
- mn=Min('check_time'), mx=Max('check_time'))
+ mn=Min('check_time'), mx=Max('check_time'))
if num_checks > 1:
check_frequency = (check_info['mx'] - check_info['mn']) \
- / (num_checks - 1)
+ / (num_checks - 1)
else:
check_frequency = None
else:
@@ -157,21 +157,21 @@ def get_mirror_statuses(cutoff=DEFAULT_CUTOFF, mirror_id=None, show_all=False):
def get_mirror_errors(cutoff=DEFAULT_CUTOFF, mirror_id=None, show_all=False):
cutoff_time = now() - cutoff
errors = MirrorLog.objects.filter(
- is_success=False, check_time__gte=cutoff_time,
- url__mirror__public=True).values('url__id', 'error').annotate(
- error_count=Count('error'), last_occurred=Max('check_time')
- ).order_by('-last_occurred', '-error_count')
+ is_success=False, check_time__gte=cutoff_time, url__mirror__public=True).values(
+ 'url__id', 'error').annotate(
+ error_count=Count('error'), last_occurred=Max('check_time')).order_by(
+ '-last_occurred', '-error_count')
if mirror_id:
errors = errors.filter(url__mirror_id=mirror_id)
if not show_all:
- errors = errors.filter(url__active=True, url__mirror__active=True,
- url__mirror__public=True)
+ errors = errors.filter(
+ url__active=True, url__mirror__active=True, url__mirror__public=True)
errors = list(errors)
to_fetch = [err['url__id'] for err in errors]
urls = MirrorUrl.objects.select_related(
- 'mirror', 'protocol').in_bulk(to_fetch)
+ 'mirror', 'protocol').in_bulk(to_fetch)
for err in errors:
err['url'] = urls[err['url__id']]
return errors
@@ -184,19 +184,19 @@ def get_mirror_url_for_download(cutoff=DEFAULT_CUTOFF):
the last batch of status rows.'''
cutoff_time = now() - cutoff
log_data = MirrorLog.objects.filter(
- check_time__gte=cutoff_time).aggregate(
- Max('check_time'), Max('last_sync'))
+ check_time__gte=cutoff_time).aggregate(
+ Max('check_time'), Max('last_sync'))
if log_data['check_time__max'] is not None:
min_check_time = log_data['check_time__max'] - timedelta(minutes=5)
min_sync_time = log_data['last_sync__max'] - timedelta(minutes=20)
best_logs = MirrorLog.objects.select_related('url').filter(
- is_success=True,
- check_time__gte=min_check_time, last_sync__gte=min_sync_time,
- url__active=True,
- url__mirror__public=True, url__mirror__active=True,
- url__protocol__default=True,
- url__protocol__protocol='https').order_by(
- 'duration')[:1]
+ is_success=True,
+ check_time__gte=min_check_time, last_sync__gte=min_sync_time,
+ url__active=True,
+ url__mirror__public=True, url__mirror__active=True,
+ url__protocol__default=True,
+ url__protocol__protocol='https').order_by(
+ 'duration')[:1]
if best_logs:
return best_logs[0].url
diff --git a/mirrors/views/__init__.py b/mirrors/views/__init__.py
index 831bbf0b..19af4535 100644
--- a/mirrors/views/__init__.py
+++ b/mirrors/views/__init__.py
@@ -9,8 +9,7 @@ from django.utils.timezone import now
from django.views.decorators.http import condition
from django_countries.fields import Country
-from ..models import (Mirror, MirrorUrl, MirrorProtocol, MirrorLog,
- CheckLocation)
+from ..models import Mirror, MirrorUrl, MirrorLog
from ..utils import get_mirror_statuses, get_mirror_errors
@@ -22,18 +21,18 @@ def mirrors(request, tier=None):
raise Http404
mirror_list = mirror_list.filter(tier=tier)
protos = MirrorUrl.objects.values_list(
- 'mirror_id', 'protocol__protocol').order_by(
- 'mirror_id', 'protocol__protocol').distinct()
+ 'mirror_id', 'protocol__protocol').order_by(
+ 'mirror_id', 'protocol__protocol').distinct()
countries = MirrorUrl.objects.values_list(
- 'mirror_id', 'country').order_by(
- 'mirror_id', 'country').distinct()
+ 'mirror_id', 'country').order_by(
+ 'mirror_id', 'country').distinct()
if not request.user.is_authenticated:
mirror_list = mirror_list.filter(public=True, active=True)
protos = protos.filter(
- mirror__public=True, mirror__active=True, active=True)
+ mirror__public=True, mirror__active=True, active=True)
countries = countries.filter(
- mirror__public=True, mirror__active=True, active=True)
+ mirror__public=True, mirror__active=True, active=True)
protos = {k: list(v) for k, v in groupby(protos, key=itemgetter(0))}
countries = {k: list(v) for k, v in groupby(countries, key=itemgetter(0))}
@@ -47,7 +46,7 @@ def mirrors(request, tier=None):
mirror.country = Country(item_countries[0][1])
return render(request, 'mirrors/mirrors.html',
- {'mirror_list': mirror_list})
+ {'mirror_list': mirror_list})
def mirror_details(request, name):
@@ -58,10 +57,8 @@ def mirror_details(request, name):
raise Http404
error_cutoff = timedelta(days=7)
- status_info = get_mirror_statuses(mirror_id=mirror.id,
- show_all=authorized)
- checked_urls = {url for url in status_info['urls'] \
- if url.mirror_id == mirror.id}
+ status_info = get_mirror_statuses(mirror_id=mirror.id, show_all=authorized)
+ checked_urls = {url for url in status_info['urls'] if url.mirror_id == mirror.id}
all_urls = mirror.urls.select_related('protocol')
if not authorized:
all_urls = all_urls.filter(active=True)
@@ -70,12 +67,12 @@ def mirror_details(request, name):
other_urls = all_urls.difference(checked_urls)
for url in other_urls:
for attr in ('last_sync', 'completion_pct', 'delay', 'duration_avg',
- 'duration_stddev', 'score'):
+ 'duration_stddev', 'score'):
setattr(url, attr, None)
all_urls = sorted(checked_urls.union(other_urls), key=attrgetter('url'))
error_logs = get_mirror_errors(mirror_id=mirror.id, cutoff=error_cutoff,
- show_all=True)
+ show_all=True)
context = {
'mirror': mirror,
@@ -88,7 +85,7 @@ def mirror_details(request, name):
def url_details(request, name, url_id):
url = get_object_or_404(MirrorUrl.objects.select_related(),
- id=url_id, mirror__name=name)
+ id=url_id, mirror__name=name)
mirror = url.mirror
authorized = request.user.is_authenticated
if not authorized and \
@@ -97,7 +94,7 @@ def url_details(request, name, url_id):
error_cutoff = timedelta(days=7)
cutoff_time = now() - error_cutoff
logs = MirrorLog.objects.select_related('location').filter(
- url=url, check_time__gte=cutoff_time).order_by('-check_time')
+ url=url, check_time__gte=cutoff_time).order_by('-check_time')
context = {
'url': url,
@@ -139,8 +136,7 @@ def status(request, tier=None):
error_logs = get_mirror_errors()
if tier is not None:
- error_logs = [log for log in error_logs
- if log['url'].mirror.tier == tier]
+ error_logs = [log for log in error_logs if log['url'].mirror.tier == tier]
context = status_info.copy()
context.update({
diff --git a/mirrors/views/api.py b/mirrors/views/api.py
index 268bf330..361e4e87 100644
--- a/mirrors/views/api.py
+++ b/mirrors/views/api.py
@@ -6,8 +6,7 @@ from django.http import Http404, HttpResponse
from django.shortcuts import get_object_or_404
from django.utils.timezone import now
-from ..models import (Mirror, MirrorUrl, MirrorProtocol, MirrorLog,
- CheckLocation)
+from ..models import (Mirror, MirrorUrl, MirrorProtocol, MirrorLog, CheckLocation)
from ..utils import get_mirror_statuses, DEFAULT_CUTOFF
@@ -15,7 +14,7 @@ class MirrorStatusJSONEncoder(DjangoJSONEncoder):
'''Base JSONEncoder extended to handle datetime.timedelta and MirrorUrl
serialization. The base class takes care of datetime.datetime types.'''
url_attributes = ('url', 'protocol', 'last_sync', 'completion_pct',
- 'delay', 'duration_avg', 'duration_stddev', 'score', 'active')
+ 'delay', 'duration_avg', 'duration_stddev', 'score', 'active')
def default(self, obj):
if isinstance(obj, timedelta):
@@ -39,14 +38,14 @@ class MirrorStatusJSONEncoder(DjangoJSONEncoder):
class ExtendedMirrorStatusJSONEncoder(MirrorStatusJSONEncoder):
'''Adds URL check history information.'''
log_attributes = ('check_time', 'last_sync', 'duration', 'is_success',
- 'location_id')
+ 'location_id')
def default(self, obj):
if isinstance(obj, MirrorUrl):
data = super(ExtendedMirrorStatusJSONEncoder, self).default(obj)
cutoff = now() - DEFAULT_CUTOFF
data['logs'] = list(obj.logs.filter(
- check_time__gte=cutoff).order_by('check_time'))
+ check_time__gte=cutoff).order_by('check_time'))
return data
if isinstance(obj, MirrorLog):
data = {attr: getattr(obj, attr) for attr in self.log_attributes}
@@ -91,16 +90,14 @@ def mirror_details_json(request, name):
mirror = get_object_or_404(Mirror, name=name)
if not authorized and (not mirror.public or not mirror.active):
raise Http404
- status_info = get_mirror_statuses(mirror_id=mirror.id,
- show_all=authorized)
+ status_info = get_mirror_statuses(mirror_id=mirror.id, show_all=authorized)
data = status_info.copy()
data['version'] = 4
data['details'] = mirror.get_full_url()
if authorized and request.user.has_perm('mirrors.change_mirror'):
data['admin_email'] = mirror.admin_email
data['alternate_email'] = mirror.alternate_email
- to_json = json.dumps(data, ensure_ascii=False,
- cls=ExtendedMirrorStatusJSONEncoder)
+ to_json = json.dumps(data, ensure_ascii=False, cls=ExtendedMirrorStatusJSONEncoder)
response = HttpResponse(to_json, content_type='application/json')
return response
diff --git a/mirrors/views/mirrorlist.py b/mirrors/views/mirrorlist.py
index 45c01819..dadb64ca 100644
--- a/mirrors/views/mirrorlist.py
+++ b/mirrors/views/mirrorlist.py
@@ -12,23 +12,21 @@ from ..utils import get_mirror_statuses
import random
+
class MirrorlistForm(forms.Form):
- country = forms.MultipleChoiceField(required=False,
- widget=SelectMultiple(attrs={'size': '12'}))
- protocol = forms.MultipleChoiceField(required=False,
- widget=CheckboxSelectMultiple)
- ip_version = forms.MultipleChoiceField(required=False,
- label="IP version", choices=(('4','IPv4'), ('6','IPv6')),
- widget=CheckboxSelectMultiple)
+ country = forms.MultipleChoiceField(required=False, widget=SelectMultiple(attrs={'size': '12'}))
+ protocol = forms.MultipleChoiceField(required=False, widget=CheckboxSelectMultiple)
+ ip_version = forms.MultipleChoiceField(
+ required=False, label="IP version", choices=(('4', 'IPv4'), ('6', 'IPv6')),
+ widget=CheckboxSelectMultiple)
use_mirror_status = forms.BooleanField(required=False)
def __init__(self, *args, **kwargs):
super(MirrorlistForm, self).__init__(*args, **kwargs)
fields = self.fields
- fields['country'].choices = [('all','All')] + self.get_countries()
+ fields['country'].choices = [('all', 'All')] + self.get_countries()
fields['country'].initial = ['all']
- protos = [(p.protocol, p.protocol) for p in
- MirrorProtocol.objects.filter(is_download=True)]
+ protos = [(p.protocol, p.protocol) for p in MirrorProtocol.objects.filter(is_download=True)]
initial = MirrorProtocol.objects.filter(is_download=True, default=True)
fields['protocol'].choices = protos
fields['protocol'].initial = [p.protocol for p in initial]
@@ -36,20 +34,20 @@ class MirrorlistForm(forms.Form):
def get_countries(self):
country_codes = set()
- country_codes.update(MirrorUrl.objects.filter(active=True,
- mirror__active=True).exclude(country='').values_list(
- 'country', flat=True).order_by().distinct())
+ country_codes.update(MirrorUrl.objects.filter(
+ active=True, mirror__active=True).exclude(country='').values_list(
+ 'country', flat=True).order_by().distinct())
code_list = [(code, countries.name(code)) for code in country_codes]
return sorted(code_list, key=itemgetter(1))
def as_div(self):
"Returns this form rendered as HTML <divs>s."
return self._html_output(
- normal_row = u'<div%(html_class_attr)s>%(label)s %(field)s%(help_text)s</div>',
- error_row = u'%s',
- row_ender = '</div>',
- help_text_html = u' <span class="helptext">%s</span>',
- errors_on_separate_row = True)
+ normal_row=u'<div%(html_class_attr)s>%(label)s %(field)s%(help_text)s</div>',
+ error_row=u'%s',
+ row_ender='</div>',
+ help_text_html=u' <span class="helptext">%s</span>',
+ errors_on_separate_row=True)
@csrf_exempt
@@ -64,12 +62,12 @@ def generate_mirrorlist(request):
ipv4 = '4' in form.cleaned_data['ip_version']
ipv6 = '6' in form.cleaned_data['ip_version']
return find_mirrors(request, countries, protocols,
- use_status, ipv4, ipv6)
+ use_status, ipv4, ipv6)
else:
form = MirrorlistForm()
return render(request, 'mirrors/mirrorlist_generate.html',
- {'mirrorlist_form': form})
+ {'mirrorlist_form': form})
def status_filter(original_urls):
@@ -88,7 +86,7 @@ def status_filter(original_urls):
def find_mirrors(request, countries=None, protocols=None, use_status=False,
- ipv4_supported=True, ipv6_supported=True):
+ ipv4_supported=True, ipv6_supported=True):
if not protocols:
protocols = MirrorProtocol.objects.filter(is_download=True)
elif hasattr(protocols, 'model') and protocols.model == MirrorProtocol:
@@ -97,8 +95,8 @@ def find_mirrors(request, countries=None, protocols=None, use_status=False,
else:
protocols = MirrorProtocol.objects.filter(protocol__in=protocols)
qset = MirrorUrl.objects.select_related().filter(
- protocol__in=protocols, active=True,
- mirror__public=True, mirror__active=True)
+ protocol__in=protocols, active=True,
+ mirror__public=True, mirror__active=True)
if countries and 'all' not in countries:
qset = qset.filter(country__in=countries)
diff --git a/news/migrations/0001_squashed_0002_news_send_announce.py b/news/migrations/0001_squashed_0002_news_send_announce.py
index 9250e4e4..59f438c5 100644
--- a/news/migrations/0001_squashed_0002_news_send_announce.py
+++ b/news/migrations/0001_squashed_0002_news_send_announce.py
@@ -27,7 +27,8 @@ class Migration(migrations.Migration):
('guid', models.CharField(editable=False, max_length=255)),
('content', models.TextField()),
('safe_mode', models.BooleanField(default=True)),
- ('author', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='news_author', to=settings.AUTH_USER_MODEL)),
+ ('author', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT,
+ related_name='news_author', to=settings.AUTH_USER_MODEL)),
('send_announce', models.BooleanField(default=True)),
],
options={
diff --git a/news/models.py b/news/models.py
index 7e321f70..340d737e 100644
--- a/news/models.py
+++ b/news/models.py
@@ -1,4 +1,5 @@
from django.db import models
+from django.db.models.signals import pre_save
from django.contrib.auth.models import User
from django.contrib.sites.models import Site
from django.utils.safestring import mark_safe
@@ -10,7 +11,7 @@ from main.utils import parse_markdown
class News(models.Model):
slug = models.SlugField(max_length=255, unique=True)
author = models.ForeignKey(User, related_name='news_author',
- on_delete=models.PROTECT)
+ on_delete=models.PROTECT)
postdate = models.DateTimeField("post date", db_index=True)
last_modified = models.DateTimeField(editable=False, db_index=True)
title = models.CharField(max_length=255)
@@ -42,13 +43,9 @@ def set_news_fields(sender, **kwargs):
if not news.postdate:
news.postdate = current_time
# http://diveintomark.org/archives/2004/05/28/howto-atom-id
- news.guid = 'tag:%s,%s:%s' % (Site.objects.get_current(),
- current_time.strftime('%Y-%m-%d'), news.get_absolute_url())
-
+ news.guid = f"tag:{Site.objects.get_current()},{current_time.strftime('%Y-%m-%d')}:{news.get_absolute_url()}"
-from django.db.models.signals import pre_save
-pre_save.connect(set_news_fields, sender=News,
- dispatch_uid="news.models")
+pre_save.connect(set_news_fields, sender=News, dispatch_uid="news.models")
# vim: set ts=4 sw=4 et:
diff --git a/news/tests.py b/news/tests.py
index b7cdd2dd..7996cad5 100644
--- a/news/tests.py
+++ b/news/tests.py
@@ -32,8 +32,8 @@ class NewsCrud(TransactionTestCase):
'admin@archlinux.org',
password)
self.client.post('/login/', {
- 'username': self.user.username,
- 'password': password
+ 'username': self.user.username,
+ 'password': password
})
def tearDown(self):
diff --git a/news/urls.py b/news/urls.py
index 111de4f5..32299542 100644
--- a/news/urls.py
+++ b/news/urls.py
@@ -1,7 +1,7 @@
from django.conf.urls import url
from django.contrib.auth.decorators import permission_required
from .views import (NewsDetailView, NewsListView, NewsCreateView, NewsEditView,
- NewsDeleteView, preview, view_redirect)
+ NewsDeleteView, preview, view_redirect)
urlpatterns = [
diff --git a/news/views.py b/news/views.py
index 24423cca..8af42b09 100644
--- a/news/views.py
+++ b/news/views.py
@@ -5,8 +5,7 @@ from django.http import HttpResponse
from django.shortcuts import get_object_or_404, redirect
from django.template import loader
from django.views.decorators.http import require_POST
-from django.views.generic import (DetailView, ListView,
- CreateView, UpdateView, DeleteView)
+from django.views.generic import DetailView, ListView, CreateView, UpdateView, DeleteView
from .models import News
from main.utils import find_unique_slug, parse_markdown
@@ -48,11 +47,12 @@ class NewsCreateView(CreateView):
if settings.MAILMAN_PASSWORD:
headers['Approved'] = settings.MAILMAN_PASSWORD
template = loader.get_template('news/news_email_notification.txt')
- EmailMessage(subject='[arch-announce] %s' % newsitem.title,
- body=template.render(ctx),
- from_email='"Arch Linux: Recent news updates: %s" <arch-announce@archlinux.org>' % newsitem.author.get_full_name(),
- to=['arch-announce@archlinux.org'],
- headers=headers).send()
+ EmailMessage(
+ subject=f'[arch-announce] {newsitem.title}',
+ body=template.render(ctx),
+ from_email=f'Arch Linux: Recent news updates: {newsitem.author.get_full_name()} <arch-announce@archlinux.org>', # noqa
+ to=['arch-announce@archlinux.org'],
+ headers=headers).send()
return super(NewsCreateView, self).form_valid(form)
diff --git a/packages/admin.py b/packages/admin.py
index 889bae25..792e65e8 100644
--- a/packages/admin.py
+++ b/packages/admin.py
@@ -1,7 +1,7 @@
from django.contrib import admin
-from .models import (PackageRelation, FlagRequest,
- Signoff, SignoffSpecification, Update)
+from .models import (PackageRelation, FlagRequest, Signoff, SignoffSpecification,
+ Update)
class PackageRelationAdmin(admin.ModelAdmin):
@@ -14,7 +14,7 @@ class PackageRelationAdmin(admin.ModelAdmin):
class FlagRequestAdmin(admin.ModelAdmin):
list_display = ('pkgbase', 'full_version', 'repo', 'created', 'who',
- 'is_spam', 'is_legitimate', 'message')
+ 'is_spam', 'is_legitimate', 'message')
list_filter = ('is_spam', 'is_legitimate', 'repo', 'created')
search_fields = ('pkgbase', 'user_email', 'message')
ordering = ('-created',)
@@ -26,7 +26,7 @@ class FlagRequestAdmin(admin.ModelAdmin):
class SignoffAdmin(admin.ModelAdmin):
list_display = ('pkgbase', 'full_version', 'arch', 'repo',
- 'user', 'created', 'revoked')
+ 'user', 'created', 'revoked')
list_filter = ('arch', 'repo', 'user', 'created')
search_fields = ('pkgbase', 'user__username')
ordering = ('-created',)
@@ -34,7 +34,7 @@ class SignoffAdmin(admin.ModelAdmin):
class SignoffSpecificationAdmin(admin.ModelAdmin):
list_display = ('pkgbase', 'full_version', 'arch', 'repo',
- 'user', 'created', 'comments')
+ 'user', 'created', 'comments')
list_filter = ('arch', 'repo', 'user', 'created')
search_fields = ('pkgbase', 'user__username')
ordering = ('-created',)
@@ -46,7 +46,7 @@ class SignoffSpecificationAdmin(admin.ModelAdmin):
class UpdateAdmin(admin.ModelAdmin):
list_display = ('pkgname', 'repo', 'arch', 'action_flag',
- 'old_version', 'new_version', 'created')
+ 'old_version', 'new_version', 'created')
list_filter = ('action_flag', 'repo', 'arch', 'created')
search_fields = ('pkgname',)
ordering = ('-created',)
diff --git a/packages/alpm.py b/packages/alpm.py
index a4c540c4..8b6bba57 100644
--- a/packages/alpm.py
+++ b/packages/alpm.py
@@ -3,7 +3,7 @@ from ctypes.util import find_library
import operator
-def load_alpm(name=None): # pragma: no cover
+def load_alpm(name=None): # pragma: no cover
# Load the alpm library and set up some of the functions we might use
if name is None:
name = find_library('alpm')
@@ -27,6 +27,7 @@ def load_alpm(name=None): # pragma: no cover
ALPM = load_alpm()
+
class AlpmAPI(object):
OPERATOR_MAP = {
'=': operator.eq,
@@ -62,14 +63,14 @@ class AlpmAPI(object):
return func(res, 0)
-def main(): # pragma: no cover
+def main(): # pragma: no cover
api = AlpmAPI()
print((api.version()))
print((api.vercmp(1, 2)))
print((api.compare_versions(1, '<', 2)))
-if __name__ == '__main__': # pragma: no cover
+if __name__ == '__main__': # pragma: no cover
main()
# vim: set ts=4 sw=4 et:
diff --git a/packages/management/commands/populate_signoffs.py b/packages/management/commands/populate_signoffs.py
index 4e4de2d5..a86fa846 100644
--- a/packages/management/commands/populate_signoffs.py
+++ b/packages/management/commands/populate_signoffs.py
@@ -28,6 +28,7 @@ logging.basicConfig(
stream=sys.stderr)
logger = logging.getLogger()
+
class Command(BaseCommand):
help = """Pull the latest commit message from SVN for a given package that
is signoff-eligible and does not have an existing comment attached"""
@@ -44,6 +45,7 @@ is signoff-eligible and does not have an existing comment attached"""
add_signoff_comments()
cleanup_signoff_comments()
+
def svn_log(pkgbase, repo):
'''Retrieve the most recent SVN log entry for the given pkgbase and
repository. The configured setting SVN_BASE_URL is used along with the
@@ -55,7 +57,7 @@ def svn_log(pkgbase, repo):
xml = XML(log_data)
revision = int(xml.find('logentry').get('revision'))
date = datetime.strptime(xml.findtext('logentry/date'),
- '%Y-%m-%dT%H:%M:%S.%fZ')
+ '%Y-%m-%dT%H:%M:%S.%fZ')
return {
'revision': revision,
'date': date,
@@ -63,6 +65,7 @@ def svn_log(pkgbase, repo):
'message': xml.findtext('logentry/msg'),
}
+
def cached_svn_log(pkgbase, repo):
'''Retrieve the cached version of the SVN log if possible, else delegate to
svn_log() to do the work and cache the result.'''
@@ -72,18 +75,22 @@ def cached_svn_log(pkgbase, repo):
log = svn_log(pkgbase, repo)
cached_svn_log.cache[key] = log
return log
+
+
cached_svn_log.cache = {}
+
def create_specification(package, log, finder):
trimmed_message = log['message'].strip()
required = package.arch.required_signoffs
spec = SignoffSpecification(pkgbase=package.pkgbase,
- pkgver=package.pkgver, pkgrel=package.pkgrel,
- epoch=package.epoch, arch=package.arch, repo=package.repo,
- comments=trimmed_message, required=required)
+ pkgver=package.pkgver, pkgrel=package.pkgrel,
+ epoch=package.epoch, arch=package.arch, repo=package.repo,
+ comments=trimmed_message, required=required)
spec.user = finder.find_by_username(log['author'])
return spec
+
def add_signoff_comments():
logger.info("getting all signoff groups")
groups = get_signoff_groups()
@@ -101,9 +108,10 @@ def add_signoff_comments():
logger.info("creating spec with SVN message for %s", group.pkgbase)
spec = create_specification(group.packages[0], log, finder)
spec.save()
- except:
+ except: # noqa
logger.exception("error getting SVN log for %s", group.pkgbase)
+
def cleanup_signoff_comments():
logger.info("getting all signoff groups")
groups = get_signoff_groups()
diff --git a/packages/migrations/0001_squashed_0003_auto_20170524_0704.py b/packages/migrations/0001_squashed_0003_auto_20170524_0704.py
index a9131139..17657307 100644
--- a/packages/migrations/0001_squashed_0003_auto_20170524_0704.py
+++ b/packages/migrations/0001_squashed_0003_auto_20170524_0704.py
@@ -24,7 +24,8 @@ class Migration(migrations.Migration):
('name', models.CharField(db_index=True, max_length=255)),
('version', models.CharField(default='', max_length=255)),
('comparison', models.CharField(default='', max_length=255)),
- ('pkg', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='conflicts', to='main.Package')),
+ ('pkg', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE,
+ related_name='conflicts', to='main.Package')),
],
options={
'ordering': ('name',),
@@ -39,8 +40,11 @@ class Migration(migrations.Migration):
('version', models.CharField(default='', max_length=255)),
('comparison', models.CharField(default='', max_length=255)),
('description', models.TextField(blank=True, null=True)),
- ('deptype', models.CharField(choices=[('D', 'Depend'), ('O', 'Optional Depend'), ('M', 'Make Depend'), ('C', 'Check Depend')], default='D', max_length=1)),
- ('pkg', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='depends', to='main.Package')),
+ ('deptype', models.CharField(
+ choices=[('D', 'Depend'), ('O', 'Optional Depend'), ('M', 'Make Depend'), ('C', 'Check Depend')],
+ default='D', max_length=1)),
+ ('pkg', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='depends',
+ to='main.Package')),
],
options={
'ordering': ('name',),
@@ -61,9 +65,11 @@ class Migration(migrations.Migration):
('num_packages', models.PositiveIntegerField(default=1, verbose_name='number of packages')),
('message', models.TextField(blank=True, verbose_name='message to developer')),
('is_spam', models.BooleanField(default=False, help_text='Is this comment from a real person?')),
- ('is_legitimate', models.BooleanField(default=True, help_text='Is this actually an out-of-date flag request?')),
+ ('is_legitimate', models.BooleanField(default=True,
+ help_text='Is this actually an out-of-date flag request?')),
('repo', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='main.Repo')),
- ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
+ ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE,
+ to=settings.AUTH_USER_MODEL)),
],
options={
'get_latest_by': 'created',
@@ -74,7 +80,8 @@ class Migration(migrations.Migration):
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255)),
- ('pkg', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='licenses', to='main.Package')),
+ ('pkg', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE,
+ related_name='licenses', to='main.Package')),
],
options={
'ordering': ('name',),
@@ -85,7 +92,8 @@ class Migration(migrations.Migration):
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(db_index=True, max_length=255)),
- ('pkg', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='groups', to='main.Package')),
+ ('pkg', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE,
+ related_name='groups', to='main.Package')),
],
options={
'ordering': ('name',),
@@ -98,7 +106,8 @@ class Migration(migrations.Migration):
('pkgbase', models.CharField(max_length=255)),
('type', models.PositiveIntegerField(choices=[(1, 'Maintainer'), (2, 'Watcher')], default=1)),
('created', models.DateTimeField(editable=False)),
- ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='package_relations', to=settings.AUTH_USER_MODEL)),
+ ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE,
+ related_name='package_relations', to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
@@ -107,7 +116,8 @@ class Migration(migrations.Migration):
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(db_index=True, max_length=255)),
('version', models.CharField(default='', max_length=255)),
- ('pkg', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='provides', to='main.Package')),
+ ('pkg', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE,
+ related_name='provides', to='main.Package')),
],
options={
'ordering': ('name',),
@@ -121,7 +131,8 @@ class Migration(migrations.Migration):
('name', models.CharField(db_index=True, max_length=255)),
('version', models.CharField(default='', max_length=255)),
('comparison', models.CharField(default='', max_length=255)),
- ('pkg', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='replaces', to='main.Package')),
+ ('pkg', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE,
+ related_name='replaces', to='main.Package')),
],
options={
'ordering': ('name',),
@@ -141,7 +152,8 @@ class Migration(migrations.Migration):
('comments', models.TextField(blank=True, null=True)),
('arch', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='main.Arch')),
('repo', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='main.Repo')),
- ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='package_signoffs', to=settings.AUTH_USER_MODEL)),
+ ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE,
+ related_name='package_signoffs', to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
@@ -153,13 +165,16 @@ class Migration(migrations.Migration):
('pkgrel', models.CharField(max_length=255)),
('epoch', models.PositiveIntegerField(default=0)),
('created', models.DateTimeField(editable=False)),
- ('required', models.PositiveIntegerField(default=2, help_text='How many signoffs are required for this package?')),
+ ('required', models.PositiveIntegerField(default=2,
+ help_text='How many signoffs are required for this package?')),
('enabled', models.BooleanField(default=True, help_text='Is this package eligible for signoffs?')),
- ('known_bad', models.BooleanField(default=False, help_text='Is this package known to be broken in some way?')),
+ ('known_bad', models.BooleanField(default=False,
+ help_text='Is this package known to be broken in some way?')),
('comments', models.TextField(blank=True, null=True)),
('arch', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='main.Arch')),
('repo', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='main.Repo')),
- ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
+ ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE,
+ to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
@@ -168,7 +183,8 @@ class Migration(migrations.Migration):
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('pkgname', models.CharField(db_index=True, max_length=255)),
('pkgbase', models.CharField(max_length=255)),
- ('action_flag', models.PositiveSmallIntegerField(choices=[(1, 'Addition'), (2, 'Change'), (3, 'Deletion')], verbose_name='action flag')),
+ ('action_flag', models.PositiveSmallIntegerField(
+ choices=[(1, 'Addition'), (2, 'Change'), (3, 'Deletion')], verbose_name='action flag')),
('created', models.DateTimeField(db_index=True, editable=False)),
('old_pkgver', models.CharField(max_length=255, null=True)),
('old_pkgrel', models.CharField(max_length=255, null=True)),
@@ -176,9 +192,12 @@ class Migration(migrations.Migration):
('new_pkgver', models.CharField(max_length=255, null=True)),
('new_pkgrel', models.CharField(max_length=255, null=True)),
('new_epoch', models.PositiveIntegerField(null=True)),
- ('arch', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='updates', to='main.Arch')),
- ('package', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='updates', to='main.Package')),
- ('repo', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='updates', to='main.Repo')),
+ ('arch', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE,
+ related_name='updates', to='main.Arch')),
+ ('package', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL,
+ related_name='updates', to='main.Package')),
+ ('repo', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE,
+ related_name='updates', to='main.Repo')),
],
options={
'get_latest_by': 'created',
diff --git a/packages/models.py b/packages/models.py
index a64a9e5a..b41b3719 100644
--- a/packages/models.py
+++ b/packages/models.py
@@ -20,8 +20,8 @@ class PackageRelation(models.Model):
MAINTAINER = 1
WATCHER = 2
TYPE_CHOICES = (
- (MAINTAINER, 'Maintainer'),
- (WATCHER, 'Watcher'),
+ (MAINTAINER, 'Maintainer'),
+ (WATCHER, 'Watcher'),
)
pkgbase = models.CharField(max_length=255)
user = models.ForeignKey(User, related_name="package_relations", on_delete=models.CASCADE)
@@ -42,8 +42,7 @@ class PackageRelation(models.Model):
return Update.objects.filter(pkgbase=self.pkgbase).latest()
def __str__(self):
- return '%s: %s (%s)' % (
- self.pkgbase, self.user, self.get_type_display())
+ return f'{self.pkgbase}: {self.user} ({self.get_typw_display()})'
class SignoffSpecificationManager(models.Manager):
@@ -51,8 +50,8 @@ class SignoffSpecificationManager(models.Manager):
'''Utility method to pull all relevant name-version fields from a
package and get a matching signoff specification.'''
return self.get(
- pkgbase=pkg.pkgbase, pkgver=pkg.pkgver, pkgrel=pkg.pkgrel,
- epoch=pkg.epoch, arch=pkg.arch, repo=pkg.repo)
+ pkgbase=pkg.pkgbase, pkgver=pkg.pkgver, pkgrel=pkg.pkgrel,
+ epoch=pkg.epoch, arch=pkg.arch, repo=pkg.repo)
def get_or_default_from_package(self, pkg):
'''utility method to pull all relevant name-version fields from a
@@ -60,8 +59,8 @@ class SignoffSpecificationManager(models.Manager):
base case.'''
try:
return self.get(
- pkgbase=pkg.pkgbase, pkgver=pkg.pkgver, pkgrel=pkg.pkgrel,
- epoch=pkg.epoch, arch=pkg.arch, repo=pkg.repo)
+ pkgbase=pkg.pkgbase, pkgver=pkg.pkgver, pkgrel=pkg.pkgrel,
+ epoch=pkg.epoch, arch=pkg.arch, repo=pkg.repo)
except SignoffSpecification.DoesNotExist:
return fake_signoff_spec(pkg.arch)
@@ -82,11 +81,11 @@ class SignoffSpecification(models.Model):
user = models.ForeignKey(User, null=True, on_delete=models.CASCADE)
created = models.DateTimeField(editable=False)
required = models.PositiveIntegerField(default=2,
- help_text="How many signoffs are required for this package?")
+ help_text="How many signoffs are required for this package?")
enabled = models.BooleanField(default=True,
- help_text="Is this package eligible for signoffs?")
+ help_text="Is this package eligible for signoffs?")
known_bad = models.BooleanField(default=False,
- help_text="Is this package known to be broken in some way?")
+ help_text="Is this package known to be broken in some way?")
comments = models.TextField(null=True, blank=True)
objects = SignoffSpecificationManager()
@@ -104,8 +103,9 @@ class SignoffSpecification(models.Model):
# Fake signoff specs for when we don't have persisted ones in the database.
# These have all necessary attributes of the real thing but are lighter weight
# and have no chance of being persisted.
-FakeSignoffSpecification = namedtuple('FakeSignoffSpecification',
- ('required', 'enabled', 'known_bad', 'comments'))
+FakeSignoffSpecification = namedtuple(
+ 'FakeSignoffSpecification',
+ ('required', 'enabled', 'known_bad', 'comments'))
def fake_signoff_spec(arch):
@@ -118,22 +118,23 @@ class SignoffManager(models.Manager):
package and get a matching signoff.'''
not_revoked = not revoked
return self.get(
- pkgbase=pkg.pkgbase, pkgver=pkg.pkgver, pkgrel=pkg.pkgrel,
- epoch=pkg.epoch, arch=pkg.arch, repo=pkg.repo,
- revoked__isnull=not_revoked, user=user)
+ pkgbase=pkg.pkgbase, pkgver=pkg.pkgver, pkgrel=pkg.pkgrel,
+ epoch=pkg.epoch, arch=pkg.arch, repo=pkg.repo,
+ revoked__isnull=not_revoked, user=user)
def get_or_create_from_package(self, pkg, user):
'''Utility method to pull all relevant name-version fields from a
package and get or create a matching signoff.'''
return self.get_or_create(
- pkgbase=pkg.pkgbase, pkgver=pkg.pkgver, pkgrel=pkg.pkgrel,
- epoch=pkg.epoch, arch=pkg.arch, repo=pkg.repo,
- revoked=None, user=user)
+ pkgbase=pkg.pkgbase, pkgver=pkg.pkgver, pkgrel=pkg.pkgrel,
+ epoch=pkg.epoch, arch=pkg.arch, repo=pkg.repo,
+ revoked=None, user=user)
def for_package(self, pkg):
return self.select_related('user').filter(
- pkgbase=pkg.pkgbase, pkgver=pkg.pkgver, pkgrel=pkg.pkgrel,
- epoch=pkg.epoch, arch=pkg.arch, repo=pkg.repo)
+ pkgbase=pkg.pkgbase, pkgver=pkg.pkgver, pkgrel=pkg.pkgrel,
+ epoch=pkg.epoch, arch=pkg.arch, repo=pkg.repo)
+
class Signoff(models.Model):
'''
@@ -157,8 +158,8 @@ class Signoff(models.Model):
@property
def packages(self):
return Package.objects.normal().filter(pkgbase=self.pkgbase,
- pkgver=self.pkgver, pkgrel=self.pkgrel, epoch=self.epoch,
- arch=self.arch, repo=self.repo)
+ pkgver=self.pkgver, pkgrel=self.pkgrel, epoch=self.epoch,
+ arch=self.arch, repo=self.repo)
@property
def full_version(self):
@@ -170,8 +171,7 @@ class Signoff(models.Model):
revoked = ''
if self.revoked:
revoked = ' (revoked)'
- return '%s-%s: %s%s' % (
- self.pkgbase, self.full_version, self.user, revoked)
+ return f'{self.pkgbase}-{self.full_version}: {self.user}{revoked}'
class FlagRequest(models.Model):
@@ -190,9 +190,9 @@ class FlagRequest(models.Model):
num_packages = models.PositiveIntegerField('number of packages', default=1)
message = models.TextField('message to developer', blank=True)
is_spam = models.BooleanField(default=False,
- help_text="Is this comment from a real person?")
+ help_text="Is this comment from a real person?")
is_legitimate = models.BooleanField(default=True,
- help_text="Is this actually an out-of-date flag request?")
+ help_text="Is this actually an out-of-date flag request?")
class Meta:
get_latest_by = 'created'
@@ -215,10 +215,10 @@ class FlagRequest(models.Model):
def get_associated_packages(self):
return Package.objects.normal().filter(
- pkgbase=self.pkgbase,
- repo__testing=self.repo.testing,
- repo__staging=self.repo.staging).order_by(
- 'pkgname', 'repo__name', 'arch__name')
+ pkgbase=self.pkgbase,
+ repo__testing=self.repo.testing,
+ repo__staging=self.repo.staging).order_by(
+ 'pkgname', 'repo__name', 'arch__name')
def __str__(self):
return '%s from %s on %s' % (self.pkgbase, self.who(), self.created)
@@ -249,9 +249,9 @@ class UpdateManager(models.Manager):
if new_pkg:
update.action_flag = CHANGE
# ensure we should even be logging this
- if (old_pkg.pkgver == new_pkg.pkgver and
- old_pkg.pkgrel == new_pkg.pkgrel and
- old_pkg.epoch == new_pkg.epoch):
+ if (old_pkg.pkgver == new_pkg.pkgver
+ and old_pkg.pkgrel == new_pkg.pkgrel
+ and old_pkg.epoch == new_pkg.epoch):
# all relevant fields were the same; e.g. a force update
return
else:
@@ -277,13 +277,12 @@ class Update(models.Model):
)
package = models.ForeignKey(Package, related_name="updates",
- null=True, on_delete=models.SET_NULL)
+ null=True, on_delete=models.SET_NULL)
repo = models.ForeignKey(Repo, related_name="updates", on_delete=models.CASCADE)
arch = models.ForeignKey(Arch, related_name="updates", on_delete=models.CASCADE)
pkgname = models.CharField(max_length=255, db_index=True)
pkgbase = models.CharField(max_length=255)
- action_flag = models.PositiveSmallIntegerField('action flag',
- choices=UPDATE_ACTION_CHOICES)
+ action_flag = models.PositiveSmallIntegerField('action flag', choices=UPDATE_ACTION_CHOICES)
created = models.DateTimeField(editable=False, db_index=True)
old_pkgver = models.CharField(max_length=255, null=True)
@@ -325,12 +324,10 @@ class Update(models.Model):
return '%s-%s' % (self.new_pkgver, self.new_pkgrel)
def elsewhere(self):
- return Package.objects.normal().filter(
- pkgname=self.pkgname, arch=self.arch)
+ return Package.objects.normal().filter(pkgname=self.pkgname, arch=self.arch)
def replacements(self):
- pkgs = Package.objects.normal().filter(
- replaces__name=self.pkgname)
+ pkgs = Package.objects.normal().filter(replaces__name=self.pkgname)
if not self.arch.agnostic:
# make sure we match architectures if possible
arches = set(Arch.objects.filter(agnostic=True))
@@ -339,12 +336,10 @@ class Update(models.Model):
return pkgs
def get_absolute_url(self):
- return '/packages/%s/%s/%s/' % (self.repo.name.lower(),
- self.arch.name, self.pkgname)
+ return f'/packages/{self.repo.name.lower()}/{self.arch.name}/{self.pkgname}/'
def __str__(self):
- return '%s of %s on %s' % (self.get_action_flag_display(),
- self.pkgname, self.created)
+ return f'{self.get_action_flag_display()} of {self.pkgname} on {self.created}'
class PackageGroup(models.Model):
@@ -386,7 +381,7 @@ class RelatedToBase(models.Model):
# TODO: this may in fact be faster- select only the fields we know will
# actually get used, saving us some bandwidth and hopefully query
# construction time. However, reality hasn't quite proved it out yet.
- #pkgs = Package.objects.select_related('repo', 'arch').only(
+ # pkgs = Package.objects.select_related('repo', 'arch').only(
# 'id', 'pkgname', 'epoch', 'pkgver', 'pkgrel',
# 'repo__id', 'repo__name', 'repo__testing', 'repo__staging',
# 'arch__id', 'arch__name').filter(pkgname=self.name)
@@ -398,9 +393,8 @@ class RelatedToBase(models.Model):
# actually satisfy the requirements
if self.comparison and self.version:
alpm = AlpmAPI()
- pkgs = [pkg for pkg in pkgs if not alpm.available or
- alpm.compare_versions(pkg.full_version, self.comparison,
- self.version)]
+ pkgs = [pkg for pkg in pkgs if not alpm.available
+ or alpm.compare_versions(pkg.full_version, self.comparison, self.version)]
if len(pkgs) == 0:
# couldn't find a package in the DB
# it should be a virtual depend (or a removed package)
@@ -426,8 +420,7 @@ class RelatedToBase(models.Model):
'''Return providers of this related package. Does *not* include exact
matches as it checks the Provision names only, use get_best_satisfier()
instead for exact matches.'''
- pkgs = Package.objects.normal().filter(
- provides__name=self.name).order_by().distinct()
+ pkgs = Package.objects.normal().filter(provides__name=self.name).order_by().distinct()
if not self.pkg.arch.agnostic:
# make sure we match architectures if possible
arches = self.pkg.applicable_arches()
@@ -443,16 +436,14 @@ class RelatedToBase(models.Model):
for provide in package.provides.all():
if provide.name != self.name:
continue
- if alpm.compare_versions(provide.version,
- self.comparison, self.version):
+ if alpm.compare_versions(provide.version, self.comparison, self.version):
new_pkgs.append(package)
pkgs = new_pkgs
# Sort providers by preference. We sort those in same staging/testing
# combination first, followed by others. We sort by a (staging,
# testing) match tuple that will be (True, True) in the best case.
- key_func = lambda x: (x.repo.staging == self.pkg.repo.staging,
- x.repo.testing == self.pkg.repo.testing)
+ key_func = lambda x: (x.repo.staging == self.pkg.repo.staging, x.repo.testing == self.pkg.repo.testing)
return sorted(pkgs, key=key_func, reverse=True)
def __str__(self):
@@ -476,8 +467,7 @@ class Depend(RelatedToBase):
pkg = models.ForeignKey(Package, related_name='depends', on_delete=models.CASCADE)
comparison = models.CharField(max_length=255, default='')
description = models.TextField(null=True, blank=True)
- deptype = models.CharField(max_length=1, default='D',
- choices=DEPTYPE_CHOICES)
+ deptype = models.CharField(max_length=1, default='D', choices=DEPTYPE_CHOICES)
def __str__(self):
'''For depends, we may also have a description and a modifier.'''
@@ -510,8 +500,7 @@ class Replacement(RelatedToBase):
# hook up some signals
for sender in (FlagRequest, PackageRelation,
- SignoffSpecification, Signoff, Update):
- pre_save.connect(set_created_field, sender=sender,
- dispatch_uid="packages.models")
+ SignoffSpecification, Signoff, Update):
+ pre_save.connect(set_created_field, sender=sender, dispatch_uid="packages.models")
# vim: set ts=4 sw=4 et:
diff --git a/packages/templatetags/package_extras.py b/packages/templatetags/package_extras.py
index 5486c61d..0f10c15b 100644
--- a/packages/templatetags/package_extras.py
+++ b/packages/templatetags/package_extras.py
@@ -29,11 +29,9 @@ def do_buildsortqs(parser, token):
try:
_, sortfield = token.split_contents()
except ValueError:
- raise template.TemplateSyntaxError(
- "%r tag requires a single argument" % token)
+ raise template.TemplateSyntaxError("%r tag requires a single argument" % token)
if not (sortfield[0] == sortfield[-1] and sortfield[0] in ('"', "'")):
- raise template.TemplateSyntaxError(
- "%r tag's argument should be in quotes" % token)
+ raise template.TemplateSyntaxError("%r tag's argument should be in quotes" % token)
return BuildQueryStringNode(sortfield[1:-1])
diff --git a/packages/tests.py b/packages/tests.py
index f2dae8cb..0b3eb4bf 100644
--- a/packages/tests.py
+++ b/packages/tests.py
@@ -326,8 +326,8 @@ class UnFlagPackage(TransactionTestCase):
self.profile.allowed_repos.add(Repo.objects.get(name='Core'))
self.profile.save()
self.client.post('/login/', {
- 'username': self.user.username,
- 'password': password
+ 'username': self.user.username,
+ 'password': password
})
def tearDown(self):
@@ -380,8 +380,8 @@ class AdoptOrphanPackage(TransactionTestCase):
self.profile.allowed_repos.add(Repo.objects.get(name='Core'))
self.profile.save()
self.client.post('/login/', {
- 'username': self.user.username,
- 'password': password
+ 'username': self.user.username,
+ 'password': password
})
def tearDown(self):
@@ -443,8 +443,8 @@ class SignOffTest(TransactionTestCase):
self.profile.allowed_repos.add(Repo.objects.get(name='Core'))
self.profile.save()
self.client.post('/login/', {
- 'username': self.user.username,
- 'password': password
+ 'username': self.user.username,
+ 'password': password
})
def tearDown(self):
diff --git a/packages/urls.py b/packages/urls.py
index 7532af29..708df96c 100644
--- a/packages/urls.py
+++ b/packages/urls.py
@@ -1,39 +1,39 @@
from django.conf.urls import include, url
-from .views.search import SearchListView
from packages import views
+from packages.views import display, flag, signoff, search
package_patterns = [
- url(r'^$', views.details),
- url(r'^json/$', views.details_json),
- url(r'^files/$', views.files),
- url(r'^files/json/$', views.files_json),
- url(r'^flag/$', views.flag),
- url(r'^flag/done/$', views.flag_confirmed, name='package-flag-confirmed'),
- url(r'^unflag/$', views.unflag),
- url(r'^unflag/all/$', views.unflag_all),
- url(r'^signoff/$', views.signoff_package),
- url(r'^signoff/revoke/$', views.signoff_package, {'revoke': True}),
- url(r'^signoff/options/$', views.signoff_options),
- url(r'^download/$', views.download),
+ url(r'^$', display.details),
+ url(r'^json/$', display.details_json),
+ url(r'^files/$', display.files),
+ url(r'^files/json/$', display.files_json),
+ url(r'^flag/$', flag.flag),
+ url(r'^flag/done/$', flag.flag_confirmed, name='package-flag-confirmed'),
+ url(r'^unflag/$', flag.unflag),
+ url(r'^unflag/all/$', flag.unflag_all),
+ url(r'^signoff/$', signoff.signoff_package),
+ url(r'^signoff/revoke/$', signoff.signoff_package, {'revoke': True}),
+ url(r'^signoff/options/$', signoff.signoff_options),
+ url(r'^download/$', display.download),
]
urlpatterns = [
- url(r'^flaghelp/$', views.flaghelp),
- url(r'^signoffs/$', views.signoffs, name='package-signoffs'),
- url(r'^signoffs/json/$', views.signoffs_json, name='package-signoffs-json'),
+ url(r'^flaghelp/$', flag.flaghelp),
+ url(r'^signoffs/$', signoff.signoffs, name='package-signoffs'),
+ url(r'^signoffs/json/$', signoff.signoffs_json, name='package-signoffs-json'),
url(r'^update/$', views.update),
- url(r'^$', SearchListView.as_view(), name='packages-search'),
- url(r'^search/json/$', views.search_json),
+ url(r'^$', search.SearchListView.as_view(), name='packages-search'),
+ url(r'^search/json/$', search.search_json),
url(r'^differences/$', views.arch_differences, name='packages-differences'),
url(r'^stale_relations/$', views.stale_relations),
url(r'^stale_relations/update/$', views.stale_relations_update),
- url(r'^(?P<name>[^ /]+)/$', views.details),
- url(r'^(?P<repo>[A-z0-9\-]+)/(?P<name>[^ /]+)/$', views.details),
+ url(r'^(?P<name>[^ /]+)/$', display.details),
+ url(r'^(?P<repo>[A-z0-9\-]+)/(?P<name>[^ /]+)/$', display.details),
# canonical package url. subviews defined above
url(r'^(?P<repo>[A-z0-9\-]+)/(?P<arch>[A-z0-9]+)/(?P<name>[^ /]+)/', include(package_patterns)),
]
diff --git a/packages/urls_groups.py b/packages/urls_groups.py
index daf26206..bc81640d 100644
--- a/packages/urls_groups.py
+++ b/packages/urls_groups.py
@@ -1,6 +1,6 @@
from django.conf.urls import url
-from packages.views import groups, group_details
+from packages.views.display import groups, group_details
urlpatterns = [
url(r'^$', groups, name='groups-list'),
diff --git a/packages/utils.py b/packages/utils.py
index 1104f7d7..c0d41c83 100644
--- a/packages/utils.py
+++ b/packages/utils.py
@@ -10,11 +10,10 @@ from django.db.models.query import QuerySet
from django.contrib.auth.models import User
from main.models import Package, PackageFile, Arch, Repo
-from main.utils import (database_vendor,
- groupby_preserve_order, PackageStandin)
+from main.utils import database_vendor, groupby_preserve_order, PackageStandin
from .models import (PackageGroup, PackageRelation,
- License, Depend, Conflict, Provision, Replacement,
- SignoffSpecification, Signoff, fake_signoff_spec)
+ License, Depend, Conflict, Provision, Replacement,
+ SignoffSpecification, Signoff, fake_signoff_spec)
from todolists.models import TodolistPackage
@@ -36,15 +35,17 @@ def parse_version(version):
def get_group_info(include_arches=None):
raw_groups = PackageGroup.objects.values_list(
- 'name', 'pkg__arch__name').order_by('name').annotate(
- cnt=Count('pkg'), last_update=Max('pkg__last_update'))
+ 'name', 'pkg__arch__name').order_by('name').annotate(
+ cnt=Count('pkg'), last_update=Max('pkg__last_update'))
# now for post_processing. we need to separate things out and add
# the count in for 'any' to all of the other architectures.
group_mapping = {}
for grp in raw_groups:
arch_groups = group_mapping.setdefault(grp[1], {})
- arch_groups[grp[0]] = {'name': grp[0], 'arch': grp[1],
- 'count': grp[2], 'last_update': grp[3]}
+ arch_groups[grp[0]] = {
+ 'name': grp[0], 'arch': grp[1],
+ 'count': grp[2], 'last_update': grp[3]
+ }
# we want to promote the count of 'any' packages in groups to the
# other architectures, and also add any 'any'-only groups
@@ -78,7 +79,7 @@ def get_split_packages_info():
matching the split pkgbase.'''
pkgnames = Package.objects.values('pkgname')
split_pkgs = Package.objects.exclude(pkgname=F('pkgbase')).exclude(
- pkgbase__in=pkgnames).values('pkgbase', 'repo', 'arch').annotate(
+ pkgbase__in=pkgnames).values('pkgbase', 'repo', 'arch').annotate(
last_update=Max('last_update')).distinct()
all_arches = Arch.objects.in_bulk({s['arch'] for s in split_pkgs})
all_repos = Repo.objects.in_bulk({s['repo'] for s in split_pkgs})
@@ -192,7 +193,7 @@ SELECT DISTINCT id
cursor.execute(sql, [PackageRelation.MAINTAINER])
to_fetch = [row[0] for row in cursor.fetchall()]
relations = PackageRelation.objects.select_related(
- 'user', 'user__userprofile').filter(
+ 'user', 'user__userprofile').filter(
id__in=to_fetch)
return relations
@@ -207,8 +208,8 @@ def attach_maintainers(packages):
packages = list(packages)
pkgbases = {p.pkgbase for p in packages if p is not None}
rels = PackageRelation.objects.filter(type=PackageRelation.MAINTAINER,
- pkgbase__in=pkgbases).values_list(
- 'pkgbase', 'user_id').order_by().distinct()
+ pkgbase__in=pkgbases).values_list(
+ 'pkgbase', 'user_id').order_by().distinct()
# get all the user objects we will need
user_ids = {rel[1] for rel in rels}
@@ -319,8 +320,7 @@ class PackageSignoffGroup(object):
return user in (s.user for s in self.signoffs if not s.revoked)
def __unicode__(self):
- return '%s-%s (%s): %d' % (
- self.pkgbase, self.version, self.arch, len(self.signoffs))
+ return f'{self.pkgbase}-{self.version} (self.arch): {len(self.signoffs)}'
def signoffs_id_query(model, repos):
@@ -359,8 +359,7 @@ def get_current_signoffs(repos):
def get_current_specifications(repos):
'''Returns a list of signoff specification objects for the given repos.'''
to_fetch = signoffs_id_query(SignoffSpecification, repos)
- return SignoffSpecification.objects.select_related('arch').in_bulk(
- to_fetch).values()
+ return SignoffSpecification.objects.select_related('arch').in_bulk(to_fetch).values()
def get_target_repo_map(repos):
@@ -390,14 +389,13 @@ def get_signoff_groups(repos=None, user=None):
repo_ids = [r.pk for r in repos]
test_pkgs = Package.objects.select_related(
- 'arch', 'repo', 'packager').filter(repo__in=repo_ids)
+ 'arch', 'repo', 'packager').filter(repo__in=repo_ids)
packages = test_pkgs.order_by('pkgname')
packages = attach_maintainers(packages)
# Filter by user if asked to do so
if user is not None:
- packages = [p for p in packages if user == p.packager
- or user in p.maintainers]
+ packages = [p for p in packages if user == p.packager or user in p.maintainers]
# Collect all pkgbase values in testing repos
pkgtorepo = get_target_repo_map(repos)
@@ -411,8 +409,7 @@ def get_signoff_groups(repos=None, user=None):
signoff_groups = []
for group in grouped:
signoff_group = PackageSignoffGroup(group)
- signoff_group.target_repo = pkgtorepo.get(signoff_group.pkgbase,
- "Unknown")
+ signoff_group.target_repo = pkgtorepo.get(signoff_group.pkgbase, "Unknown")
signoff_group.find_signoffs(signoffs)
signoff_group.find_specification(specs)
signoff_groups.append(signoff_group)
@@ -420,16 +417,16 @@ def get_signoff_groups(repos=None, user=None):
return signoff_groups
-DEPENDENCY_TYPES = [('D', 'depends'), ('O', 'optdepends'),
- ('M', 'makedepends'), ('C', 'checkdepends')]
+DEPENDENCY_TYPES = [('D', 'depends'), ('O', 'optdepends'),
+ ('M', 'makedepends'), ('C', 'checkdepends')]
+
class PackageJSONEncoder(DjangoJSONEncoder):
- pkg_attributes = ['pkgname', 'pkgbase', 'repo', 'arch', 'pkgver',
- 'pkgrel', 'epoch', 'pkgdesc', 'url', 'filename', 'compressed_size',
- 'installed_size', 'build_date', 'last_update', 'flag_date',
- 'maintainers', 'packager']
- pkg_list_attributes = ['groups', 'licenses', 'conflicts',
- 'provides', 'replaces']
+ pkg_attributes = ['pkgname', 'pkgbase', 'repo', 'arch', 'pkgver', 'pkgrel',
+ 'epoch', 'pkgdesc', 'url', 'filename', 'compressed_size',
+ 'installed_size', 'build_date', 'last_update', 'flag_date',
+ 'maintainers', 'packager']
+ pkg_list_attributes = ['groups', 'licenses', 'conflicts', 'provides', 'replaces']
todolistpackage_attributes = ['status_str']
def default(self, obj):
diff --git a/packages/views/__init__.py b/packages/views/__init__.py
index 904043af..b294190a 100644
--- a/packages/views/__init__.py
+++ b/packages/views/__init__.py
@@ -3,7 +3,6 @@ import json
from django.contrib import messages
from django.contrib.auth.decorators import permission_required
-from django.contrib.auth.models import User
from django.core.cache import cache
from django.db.models import Q
from django.http import HttpResponse
@@ -15,13 +14,6 @@ from main.models import Package
from ..models import PackageRelation
from ..utils import multilib_differences, get_wrong_permissions
-# make other views available from this same package
-from .display import (details, groups, group_details, files, details_json,
- files_json, download)
-from .flag import flaghelp, flag, flag_confirmed, unflag, unflag_all
-from .search import search_json
-from .signoff import signoffs, signoff_package, signoff_options, signoffs_json
-
@require_safe
@cache_control(public=True, max_age=86400)
@@ -29,8 +21,8 @@ def opensearch(request):
domain = "%s://%s" % (request.scheme, request.META.get('HTTP_HOST'))
return render(request, 'packages/opensearch.xml',
- {'domain': domain},
- content_type='application/opensearchdescription+xml')
+ {'domain': domain},
+ content_type='application/opensearchdescription+xml')
@require_safe
@@ -40,15 +32,14 @@ def opensearch_suggest(request):
if search_term == '':
return HttpResponse('', content_type='application/x-suggestions+json')
- cache_key = 'opensearch:packages:' + \
- hashlib.md5(search_term.encode('utf-8')).hexdigest()
+ cache_key = 'opensearch:packages:' + hashlib.md5(search_term.encode('utf-8')).hexdigest()
to_json = cache.get(cache_key, None)
if to_json is None:
# Package names are lowercase by convention
q = Q(pkgname__istartswith=search_term)
names = Package.objects.filter(q).values_list(
- 'pkgname', flat=True).order_by('pkgname').distinct()[:10]
+ 'pkgname', flat=True).order_by('pkgname').distinct()[:10]
results = (search_term, tuple(names))
to_json = json.dumps(results, ensure_ascii=False)
cache.set(cache_key, to_json, 613)
@@ -65,13 +56,12 @@ def update(request):
repos = request.user.userprofile.allowed_repos.all()
pkgs = Package.objects.filter(id__in=ids, repo__in=repos)
disallowed_pkgs = Package.objects.filter(id__in=ids).exclude(
- repo__in=repos)
+ repo__in=repos)
if disallowed_pkgs:
messages.warning(request,
- "You do not have permission to adopt: %s." % (
- ' '.join([p.pkgname for p in disallowed_pkgs])
- ))
+ "You do not have permission to adopt: %s." %
+ (' '.join([p.pkgname for p in disallowed_pkgs])))
for pkg in pkgs:
if request.user in pkg.maintainers:
@@ -90,10 +80,10 @@ def update(request):
for pkg in Package.objects.filter(id__in=ids):
if request.user in pkg.maintainers:
rels = PackageRelation.objects.filter(
- pkgbase=pkg.pkgbase,
- user=request.user,
- type=PackageRelation.MAINTAINER
- )
+ pkgbase=pkg.pkgbase,
+ user=request.user,
+ type=PackageRelation.MAINTAINER
+ )
count += rels.count()
rels.delete()
@@ -106,10 +96,11 @@ def update(request):
def arch_differences(request):
context = {
- 'multilib_differences': multilib_differences()
+ 'multilib_differences': multilib_differences()
}
return render(request, 'packages/differences.html', context)
+
@permission_required('main.change_package')
def stale_relations(request):
relations = PackageRelation.objects.select_related('user')
@@ -117,16 +108,17 @@ def stale_relations(request):
inactive_user = relations.filter(user__is_active=False)
missing_pkgbase = relations.exclude(
- pkgbase__in=pkgbases).order_by('pkgbase')
+ pkgbase__in=pkgbases).order_by('pkgbase')
wrong_permissions = get_wrong_permissions()
context = {
- 'inactive_user': inactive_user,
- 'missing_pkgbase': missing_pkgbase,
- 'wrong_permissions': wrong_permissions,
+ 'inactive_user': inactive_user,
+ 'missing_pkgbase': missing_pkgbase,
+ 'wrong_permissions': wrong_permissions,
}
return render(request, 'packages/stale_relations.html', context)
+
@permission_required('packages.delete_packagerelation')
@require_POST
def stale_relations_update(request):
diff --git a/packages/views/display.py b/packages/views/display.py
index 76849cfc..88307f7e 100644
--- a/packages/views/display.py
+++ b/packages/views/display.py
@@ -14,7 +14,7 @@ from ..utils import get_group_info, PackageJSONEncoder
def arch_plus_agnostic(arch):
- arches = [ arch ]
+ arches = [arch]
arches.extend(Arch.objects.filter(agnostic=True).order_by())
return arches
@@ -24,8 +24,8 @@ def split_package_details(request, name, repo, arch):
name. If so, we can show a listing page for the entire set of packages.'''
arches = arch_plus_agnostic(arch)
pkgs = Package.objects.normal().filter(pkgbase=name,
- repo__testing=repo.testing, repo__staging=repo.staging,
- arch__in=arches).order_by('pkgname')
+ repo__testing=repo.testing, repo__staging=repo.staging,
+ arch__in=arches).order_by('pkgname')
if not pkgs:
return None
# we have packages, but ensure at least one is in the given repo
@@ -49,7 +49,7 @@ def recently_removed_package(request, name, repo, arch, cutoff=CUTOFF):
requester in the right direction.'''
arches = arch_plus_agnostic(arch)
match = Update.objects.select_related('arch', 'repo').filter(
- pkgname=name, repo=repo, arch__in=arches)
+ pkgname=name, repo=repo, arch__in=arches)
if cutoff is not None:
when = now() - cutoff
match = match.filter(created__gte=when)
@@ -100,7 +100,7 @@ def redirect_agnostic(request, name, repo, arch):
# except only one matching result
pkgs = Package.objects.select_related(
'arch', 'repo', 'packager').filter(pkgname=name,
- repo=repo, arch__agnostic=True)[:2]
+ repo=repo, arch__agnostic=True)[:2]
if len(pkgs) == 1:
return redirect(pkgs[0], permanent=True)
return None
@@ -125,15 +125,15 @@ def details(request, name='', repo='', arch=''):
repo_obj = get_object_or_404(Repo, name__iexact=repo)
try:
pkg = Package.objects.select_related(
- 'arch', 'repo', 'packager').get(pkgname=name,
- repo=repo_obj, arch=arch_obj)
+ 'arch', 'repo', 'packager').get(pkgname=name,
+ repo=repo_obj, arch=arch_obj)
if request.method == 'HEAD':
return empty_response()
return render(request, 'packages/details.html', {'pkg': pkg})
except Package.DoesNotExist:
# attempt a variety of fallback options before 404ing
options = (redirect_agnostic, split_package_details,
- recently_removed_package, replaced_package)
+ recently_removed_package, replaced_package)
for method in options:
ret = method(request, name, repo_obj, arch_obj)
if ret:
@@ -161,7 +161,7 @@ def group_details(request, arch, name):
arch = get_object_or_404(Arch, name=arch)
arches = arch_plus_agnostic(arch)
pkgs = Package.objects.normal().filter(
- groups__name=name, arch__in=arches).order_by('pkgname')
+ groups__name=name, arch__in=arches).order_by('pkgname')
if not pkgs:
raise Http404
context = {
@@ -175,7 +175,7 @@ def group_details(request, arch, name):
def files(request, name, repo, arch):
pkg = get_object_or_404(Package.objects.normal(),
- pkgname=name, repo__name__iexact=repo, arch__name=arch)
+ pkgname=name, repo__name__iexact=repo, arch__name=arch)
# files are inserted in sorted order, so preserve that
fileslist = PackageFile.objects.filter(pkg=pkg).order_by('id')
dir_count = sum(1 for f in fileslist if f.is_directory)
@@ -192,14 +192,14 @@ def files(request, name, repo, arch):
def details_json(request, name, repo, arch):
pkg = get_object_or_404(Package.objects.normal(),
- pkgname=name, repo__name__iexact=repo, arch__name=arch)
+ pkgname=name, repo__name__iexact=repo, arch__name=arch)
to_json = json.dumps(pkg, ensure_ascii=False, cls=PackageJSONEncoder)
return HttpResponse(to_json, content_type='application/json')
def files_json(request, name, repo, arch):
pkg = get_object_or_404(Package.objects.normal(),
- pkgname=name, repo__name__iexact=repo, arch__name=arch)
+ pkgname=name, repo__name__iexact=repo, arch__name=arch)
# files are inserted in sorted order, so preserve that
fileslist = PackageFile.objects.filter(pkg=pkg).order_by('id')
dir_count = sum(1 for f in fileslist if f.is_directory)
@@ -220,7 +220,7 @@ def files_json(request, name, repo, arch):
def download(request, name, repo, arch):
pkg = get_object_or_404(Package.objects.normal(),
- pkgname=name, repo__name__iexact=repo, arch__name=arch)
+ pkgname=name, repo__name__iexact=repo, arch__name=arch)
url = get_mirror_url_for_download()
if not url:
raise Http404
@@ -229,7 +229,8 @@ def download(request, name, repo, arch):
# grab the first non-any arch to fake the download path
arch = Arch.objects.exclude(agnostic=True)[0].name
url = '{host}{repo}/os/{arch}/{filename}'.format(host=url.url,
- repo=pkg.repo.name.lower(), arch=arch, filename=pkg.filename)
+ repo=pkg.repo.name.lower(),
+ arch=arch, filename=pkg.filename)
return redirect(url)
# vim: set ts=4 sw=4 et:
diff --git a/packages/views/flag.py b/packages/views/flag.py
index 91995ee7..93aa0aaf 100644
--- a/packages/views/flag.py
+++ b/packages/views/flag.py
@@ -17,12 +17,12 @@ from main.models import Package
class FlagForm(forms.Form):
email = forms.EmailField(label='E-mail Address')
message = forms.CharField(label='Message To Developer',
- widget=forms.Textarea)
+ widget=forms.Textarea)
# The field below is used to filter out bots that blindly fill out all
# input elements
website = forms.CharField(label='',
- widget=forms.TextInput(),
- required=False)
+ widget=forms.TextInput(),
+ required=False)
def __init__(self, *args, **kwargs):
# we remove the 'email' field if this form is being shown to a
@@ -37,8 +37,7 @@ class FlagForm(forms.Form):
# make sure the message isn't garbage (only punctuation or whitespace)
# and ensure a certain minimum length
if re.match(r'^[^0-9A-Za-z]+$', data) or len(data) < 3:
- raise forms.ValidationError(
- "Enter a valid and useful out-of-date message.")
+ raise forms.ValidationError("Enter a valid and useful out-of-date message.")
return data
@@ -50,16 +49,16 @@ def flaghelp(request):
@never_cache
def flag(request, name, repo, arch):
pkg = get_object_or_404(Package.objects.normal(),
- pkgname=name, repo__name__iexact=repo, arch__name=arch)
+ pkgname=name, repo__name__iexact=repo, arch__name=arch)
if pkg.flag_date is not None:
# already flagged. do nothing.
return render(request, 'packages/flagged.html', {'pkg': pkg})
# find all packages from (hopefully) the same PKGBUILD
pkgs = Package.objects.normal().filter(
- pkgbase=pkg.pkgbase, flag_date__isnull=True,
- repo__testing=pkg.repo.testing,
- repo__staging=pkg.repo.staging).order_by(
- 'pkgname', 'repo__name', 'arch__name')
+ pkgbase=pkg.pkgbase, flag_date__isnull=True,
+ repo__testing=pkg.repo.testing,
+ repo__staging=pkg.repo.staging).order_by(
+ 'pkgname', 'repo__name', 'arch__name')
authenticated = request.user.is_authenticated
@@ -71,7 +70,7 @@ def flag(request, name, repo, arch):
# find a common version if there is one available to store
versions = set((pkg.pkgver, pkg.pkgrel, pkg.epoch)
- for pkg in flagged_pkgs)
+ for pkg in flagged_pkgs)
if len(versions) == 1:
version = versions.pop()
else:
@@ -90,10 +89,10 @@ def flag(request, name, repo, arch):
pkgs.update(flag_date=current_time)
# store our flag request
flag_request = FlagRequest(created=current_time,
- user_email=email, message=message,
- ip_address=ip_addr, pkgbase=pkg.pkgbase,
- repo=pkg.repo, pkgver=version[0], pkgrel=version[1],
- epoch=version[2], num_packages=len(flagged_pkgs))
+ user_email=email, message=message,
+ ip_address=ip_addr, pkgbase=pkg.pkgbase,
+ repo=pkg.repo, pkgver=version[0], pkgrel=version[1],
+ epoch=version[2], num_packages=len(flagged_pkgs))
if authenticated:
flag_request.user = request.user
flag_request.save()
@@ -103,12 +102,10 @@ def flag(request, name, repo, arch):
maints = pkg.maintainers
if not maints:
toemail = settings.NOTIFICATIONS
- subject = 'Orphan %s package [%s] marked out-of-date' % \
- (pkg.repo.name, pkg.pkgname)
+ subject = f'Orphan {pkg.repo.name} package [{pkg.pkgname}] marked out-of-date'
else:
toemail = []
- subject = '%s package [%s] marked out-of-date' % \
- (pkg.repo.name, pkg.pkgname)
+ subject = f'{pkg.repo.name} package [{pkg.pkgname}] marked out-of-date'
for maint in maints:
if maint.userprofile.notify is True:
toemail.append(maint.email)
@@ -123,15 +120,14 @@ def flag(request, name, repo, arch):
'packages': flagged_pkgs,
}
msg = EmailMessage(subject,
- tmpl.render(ctx),
- 'Arch Website Notification <nobody@archlinux.org>',
- toemail,
- headers={"Reply-To": email }
- )
+ tmpl.render(ctx),
+ 'Arch Website Notification <nobody@archlinux.org>',
+ toemail,
+ headers={"Reply-To": email})
msg.send(fail_silently=True)
return redirect('package-flag-confirmed', name=name, repo=repo,
- arch=arch)
+ arch=arch)
else:
form = FlagForm(authenticated=authenticated)
@@ -142,34 +138,37 @@ def flag(request, name, repo, arch):
}
return render(request, 'packages/flag.html', context)
+
def flag_confirmed(request, name, repo, arch):
pkg = get_object_or_404(Package,
- pkgname=name, repo__name__iexact=repo, arch__name=arch)
+ pkgname=name, repo__name__iexact=repo, arch__name=arch)
pkgs = Package.objects.normal().filter(
- pkgbase=pkg.pkgbase, flag_date=pkg.flag_date,
- repo__testing=pkg.repo.testing,
- repo__staging=pkg.repo.staging).order_by(
- 'pkgname', 'repo__name', 'arch__name')
+ pkgbase=pkg.pkgbase, flag_date=pkg.flag_date,
+ repo__testing=pkg.repo.testing,
+ repo__staging=pkg.repo.staging).order_by(
+ 'pkgname', 'repo__name', 'arch__name')
context = {'package': pkg, 'packages': pkgs}
return render(request, 'packages/flag_confirmed.html', context)
+
@permission_required('main.change_package')
def unflag(request, name, repo, arch):
pkg = get_object_or_404(Package.objects.normal(),
- pkgname=name, repo__name__iexact=repo, arch__name=arch)
+ pkgname=name, repo__name__iexact=repo, arch__name=arch)
pkg.flag_date = None
pkg.save()
return redirect(pkg)
+
@permission_required('main.change_package')
def unflag_all(request, name, repo, arch):
pkg = get_object_or_404(Package.objects.normal(),
- pkgname=name, repo__name__iexact=repo, arch__name=arch)
+ pkgname=name, repo__name__iexact=repo, arch__name=arch)
# find all packages from (hopefully) the same PKGBUILD
pkgs = Package.objects.filter(pkgbase=pkg.pkgbase,
- repo__testing=pkg.repo.testing, repo__staging=pkg.repo.staging)
+ repo__testing=pkg.repo.testing, repo__staging=pkg.repo.staging)
pkgs.update(flag_date=None)
return redirect(pkg)
diff --git a/packages/views/search.py b/packages/views/search.py
index b8f18ed5..875fbd65 100644
--- a/packages/views/search.py
+++ b/packages/views/search.py
@@ -28,8 +28,8 @@ class PackageSearchForm(forms.Form):
maintainer = forms.ChoiceField(required=False)
packager = forms.ChoiceField(required=False)
flagged = forms.ChoiceField(
- choices=[('', 'All')] + make_choice(['Flagged', 'Not Flagged']),
- required=False)
+ choices=[('', 'All')] + make_choice(['Flagged', 'Not Flagged']),
+ required=False)
def __init__(self, *args, **kwargs):
show_staging = kwargs.pop('show_staging', False)
@@ -37,20 +37,18 @@ class PackageSearchForm(forms.Form):
repos = Repo.objects.all()
if not show_staging:
repos = repos.filter(staging=False)
- self.fields['repo'].choices = make_choice(
- [repo.name for repo in repos])
- self.fields['arch'].choices = make_choice(
- [arch.name for arch in Arch.objects.all()])
+ self.fields['repo'].choices = make_choice([repo.name for repo in repos])
+ self.fields['arch'].choices = make_choice([arch.name for arch in Arch.objects.all()])
self.fields['q'].widget.attrs.update({"size": "30"})
profile_ids = UserProfile.allowed_repos.through.objects.values('userprofile_id')
people = User.objects.filter(
- is_active=True, userprofile__id__in=profile_ids).order_by(
- 'first_name', 'last_name')
+ is_active=True, userprofile__id__in=profile_ids).order_by(
+ 'first_name', 'last_name')
maintainers = [('', 'All'), ('orphan', 'Orphan')] + \
- [(p.username, p.get_full_name()) for p in people]
+ [(p.username, p.get_full_name()) for p in people]
packagers = [('', 'All'), ('unknown', 'Unknown')] + \
- [(p.username, p.get_full_name()) for p in people]
+ [(p.username, p.get_full_name()) for p in people]
self.fields['maintainer'].choices = maintainers
self.fields['packager'].choices = packagers
@@ -66,26 +64,23 @@ class PackageSearchForm(forms.Form):
def parse_form(form, packages):
if form.cleaned_data['repo']:
- packages = packages.filter(
- repo__name__in=form.cleaned_data['repo'])
+ packages = packages.filter(repo__name__in=form.cleaned_data['repo'])
if form.cleaned_data['arch']:
- packages = packages.filter(
- arch__name__in=form.cleaned_data['arch'])
+ packages = packages.filter(arch__name__in=form.cleaned_data['arch'])
if form.cleaned_data['maintainer'] == 'orphan':
inner_q = PackageRelation.objects.all().values('pkgbase')
packages = packages.exclude(pkgbase__in=inner_q)
elif form.cleaned_data['maintainer']:
inner_q = PackageRelation.objects.filter(
- user__username=form.cleaned_data['maintainer']).values('pkgbase')
+ user__username=form.cleaned_data['maintainer']).values('pkgbase')
packages = packages.filter(pkgbase__in=inner_q)
if form.cleaned_data['packager'] == 'unknown':
packages = packages.filter(packager__isnull=True)
elif form.cleaned_data['packager']:
- packages = packages.filter(
- packager__username=form.cleaned_data['packager'])
+ packages = packages.filter(packager__username=form.cleaned_data['packager'])
if form.cleaned_data['flagged'] == 'Flagged':
packages = packages.filter(flag_date__isnull=False)
@@ -131,7 +126,7 @@ class SearchListView(ListView):
if request.method == 'HEAD':
return empty_response()
self.form = PackageSearchForm(data=request.GET,
- show_staging=self.request.user.is_authenticated)
+ show_staging=self.request.user.is_authenticated)
return super(SearchListView, self).get(request, *args, **kwargs)
def get_queryset(self):
@@ -169,14 +164,13 @@ def search_json(request):
if request.GET:
form = PackageSearchForm(data=request.GET,
- show_staging=request.user.is_authenticated)
+ show_staging=request.user.is_authenticated)
if form.is_valid():
form_limit = form.cleaned_data.get('limit', limit)
limit = min(limit, form_limit) if form_limit else limit
container['limit'] = limit
- packages = Package.objects.select_related('arch', 'repo',
- 'packager')
+ packages = Package.objects.select_related('arch', 'repo', 'packager')
if not request.user.is_authenticated:
packages = packages.filter(repo__staging=False)
packages = parse_form(form, packages)
diff --git a/packages/views/signoff.py b/packages/views/signoff.py
index 7c2d5224..5e05c28a 100644
--- a/packages/views/signoff.py
+++ b/packages/views/signoff.py
@@ -16,7 +16,8 @@ from django.views.decorators.cache import never_cache
from main.models import Package, Arch, Repo
from ..models import SignoffSpecification, Signoff
from ..utils import (get_signoff_groups, approved_by_signoffs,
- PackageSignoffGroup)
+ PackageSignoffGroup)
+
@permission_required('packages.change_signoff')
def signoffs(request):
@@ -31,19 +32,19 @@ def signoffs(request):
}
return render(request, 'packages/signoffs.html', context)
+
@permission_required('packages.change_signoff')
@never_cache
def signoff_package(request, name, repo, arch, revoke=False):
packages = get_list_or_404(Package, pkgbase=name,
- arch__name=arch, repo__name__iexact=repo, repo__testing=True)
+ arch__name=arch, repo__name__iexact=repo, repo__testing=True)
package = packages[0]
spec = SignoffSpecification.objects.get_or_default_from_package(package)
if revoke:
try:
- signoff = Signoff.objects.get_from_package(
- package, request.user, False)
+ signoff = Signoff.objects.get_from_package(package, request.user, False)
except Signoff.DoesNotExist:
raise Http404
signoff.revoked = now()
@@ -53,10 +54,8 @@ def signoff_package(request, name, repo, arch, revoke=False):
# ensure we should even be accepting signoffs
if spec.known_bad or not spec.enabled:
return render(request, '403.html', status=403)
- signoff, created = Signoff.objects.get_or_create_from_package(
- package, request.user)
- signoffs = Signoff.objects.for_package(package).filter(
- revoked__isnull=True)
+ signoff, created = Signoff.objects.get_or_create_from_package(package, request.user)
+ signoffs = Signoff.objects.for_package(package).filter(revoked__isnull=True)
if signoffs.count() == spec.required:
packager = package.packager
@@ -64,8 +63,7 @@ def signoff_package(request, name, repo, arch, revoke=False):
# TODO: Handle notification when packager does not exist
if packager:
toemail = [packager.email]
- subject = f'{package.repo.name} package ' + \
- f'[{package.pkgname} {package.full_version}] approved'
+ subject = f'{package.repo.name} package [{package.pkgname} {package.full_version}] approved'
# send notification email to the maintainers
tmpl = loader.get_template('packages/approved.txt')
@@ -74,10 +72,9 @@ def signoff_package(request, name, repo, arch, revoke=False):
'pkg': package,
}
msg = EmailMessage(subject,
- tmpl.render(ctx),
- 'Arch Website Notification <nobody@archlinux.org>',
- toemail,
- )
+ tmpl.render(ctx),
+ 'Arch Website Notification <nobody@archlinux.org>',
+ toemail)
msg.send(fail_silently=True)
all_signoffs = Signoff.objects.for_package(package)
@@ -93,25 +90,27 @@ def signoff_package(request, name, repo, arch, revoke=False):
'user': str(request.user),
}
return HttpResponse(json.dumps(data, ensure_ascii=False),
- content_type='application/json')
+ content_type='application/json')
return redirect('package-signoffs')
+
class SignoffOptionsForm(forms.ModelForm):
apply_all = forms.BooleanField(required=False,
- help_text="Apply these options to all architectures?")
+ help_text="Apply these options to all architectures?")
class Meta:
model = SignoffSpecification
fields = ('required', 'enabled', 'known_bad', 'comments')
+
def _signoff_options_all(request, name, repo):
seen_ids = set()
with transaction.atomic():
# find or create a specification for all architectures, then
# graft the form data onto them
packages = Package.objects.filter(pkgbase=name,
- repo__name__iexact=repo, repo__testing=True)
+ repo__name__iexact=repo, repo__testing=True)
for package in packages:
try:
spec = SignoffSpecification.objects.get_from_package(package)
@@ -119,9 +118,9 @@ def _signoff_options_all(request, name, repo):
continue
except SignoffSpecification.DoesNotExist:
spec = SignoffSpecification(pkgbase=package.pkgbase,
- pkgver=package.pkgver, pkgrel=package.pkgrel,
- epoch=package.epoch, arch=package.arch,
- repo=package.repo)
+ pkgver=package.pkgver, pkgrel=package.pkgrel,
+ epoch=package.epoch, arch=package.arch,
+ repo=package.repo)
if spec.user is None:
spec.user = request.user
@@ -131,11 +130,12 @@ def _signoff_options_all(request, name, repo):
form.save()
seen_ids.add(form.instance.pk)
+
@permission_required('main.change_package')
@never_cache
def signoff_options(request, name, repo, arch):
packages = get_list_or_404(Package, pkgbase=name,
- arch__name=arch, repo__name__iexact=repo, repo__testing=True)
+ arch__name=arch, repo__name__iexact=repo, repo__testing=True)
package = packages[0]
if request.user != package.packager and \
@@ -147,8 +147,8 @@ def signoff_options(request, name, repo, arch):
except SignoffSpecification.DoesNotExist:
# create a fake one, but don't save it just yet
spec = SignoffSpecification(pkgbase=package.pkgbase,
- pkgver=package.pkgver, pkgrel=package.pkgrel,
- epoch=package.epoch, arch=package.arch, repo=package.repo)
+ pkgver=package.pkgver, pkgrel=package.pkgrel,
+ epoch=package.epoch, arch=package.arch, repo=package.repo)
if spec.user is None:
spec.user = request.user
@@ -171,11 +171,12 @@ def signoff_options(request, name, repo, arch):
}
return render(request, 'packages/signoff_options.html', context)
+
class SignoffJSONEncoder(DjangoJSONEncoder):
'''Base JSONEncoder extended to handle all serialization of all classes
related to signoffs.'''
signoff_group_attrs = ['arch', 'last_update', 'maintainers', 'packager',
- 'pkgbase', 'repo', 'signoffs', 'target_repo', 'version']
+ 'pkgbase', 'repo', 'signoffs', 'target_repo', 'version']
signoff_spec_attrs = ['required', 'enabled', 'known_bad', 'comments']
signoff_attrs = ['user', 'created', 'revoked']
@@ -187,7 +188,7 @@ class SignoffJSONEncoder(DjangoJSONEncoder):
data['package_count'] = len(obj.packages)
data['approved'] = obj.approved()
data.update((attr, getattr(obj.specification, attr))
- for attr in self.signoff_spec_attrs)
+ for attr in self.signoff_spec_attrs)
return data
elif isinstance(obj, Signoff):
return {attr: getattr(obj, attr) for attr in self.signoff_attrs}
@@ -199,6 +200,7 @@ class SignoffJSONEncoder(DjangoJSONEncoder):
return list(obj)
return super(SignoffJSONEncoder, self).default(obj)
+
@permission_required('packages.change_signoff')
def signoffs_json(request):
signoff_groups = sorted(get_signoff_groups(), key=attrgetter('pkgbase'))
diff --git a/planet/admin.py b/planet/admin.py
index 59f02a0e..db91f9ae 100644
--- a/planet/admin.py
+++ b/planet/admin.py
@@ -8,16 +8,19 @@ class FeedItemAdmin(admin.ModelAdmin):
list_filter = ('publishdate',)
search_fields = ('title',)
+
class FeedAdmin(admin.ModelAdmin):
list_display = ('title', 'website',)
list_filter = ('title',)
search_fields = ('title',)
+
class PlanetAdmin(admin.ModelAdmin):
list_display = ('name', 'website',)
list_filter = ('name',)
search_fields = ('name',)
+
admin.site.register(Feed, FeedAdmin)
admin.site.register(FeedItem, FeedItemAdmin)
admin.site.register(Planet, PlanetAdmin)
diff --git a/planet/migrations/0001_initial.py b/planet/migrations/0001_initial.py
index 948b2532..a7592cef 100644
--- a/planet/migrations/0001_initial.py
+++ b/planet/migrations/0001_initial.py
@@ -50,7 +50,8 @@ class Migration(migrations.Migration):
('author', models.CharField(max_length=255)),
('publishdate', models.DateTimeField(db_index=True, verbose_name='publish date')),
('url', models.CharField(max_length=255, verbose_name='URL')),
- ('feed', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='feed', to='planet.Feed')),
+ ('feed', models.ForeignKey(
+ null=True, on_delete=django.db.models.deletion.CASCADE, related_name='feed', to='planet.Feed')),
],
options={
'verbose_name_plural': 'Feed Items',
diff --git a/planet/models.py b/planet/models.py
index 2aaeb7f5..0eb5eabf 100644
--- a/planet/models.py
+++ b/planet/models.py
@@ -19,6 +19,7 @@ class Feed(models.Model):
get_latest_by = 'title'
ordering = ('-title',)
+
class FeedItem(models.Model):
title = models.CharField(max_length=255)
summary = models.CharField(max_length=FEEDITEM_SUMMARY_LIMIT)
@@ -40,6 +41,7 @@ class FeedItem(models.Model):
get_latest_by = 'publishdate'
ordering = ('-publishdate',)
+
class Planet(models.Model):
'''
The planet model contains related Arch Linux planet instances.
diff --git a/planet/tests/test_command.py b/planet/tests/test_command.py
index e93ce51a..5c2fd9b3 100644
--- a/planet/tests/test_command.py
+++ b/planet/tests/test_command.py
@@ -14,6 +14,7 @@ class Result(dict):
def get(self, value):
return getattr(self, value)
+
class Entry(dict):
title = 'title'
description = 'lorem ipsum'
diff --git a/releng/admin.py b/releng/admin.py
index 251cc90a..ef924c4b 100644
--- a/releng/admin.py
+++ b/releng/admin.py
@@ -2,9 +2,10 @@ from django.contrib import admin
from .models import Release
+
class ReleaseAdmin(admin.ModelAdmin):
list_display = ('version', 'release_date', 'kernel_version', 'available',
- 'created')
+ 'created')
list_filter = ('available', 'release_date')
readonly_fields = ('created', 'last_modified')
diff --git a/releng/migrations/0001_squashed_0005_auto_20180616_0947.py b/releng/migrations/0001_squashed_0005_auto_20180616_0947.py
index 76f10f60..4269ebf4 100644
--- a/releng/migrations/0001_squashed_0005_auto_20180616_0947.py
+++ b/releng/migrations/0001_squashed_0005_auto_20180616_0947.py
@@ -16,6 +16,7 @@ def release_populate_last_modified_forwards(apps, schema_editor):
Release = apps.get_model('releng', 'Release')
Release.objects.update(last_modified=models.F('created'))
+
def release_populate_last_modified_backwards(apps, schema_editor):
pass
@@ -144,7 +145,8 @@ class Migration(migrations.Migration):
('available', models.BooleanField(default=True)),
('info', models.TextField(blank=True, verbose_name='Public information')),
('torrent_data', models.TextField(blank=True, help_text='base64-encoded torrent file')),
- ('last_modified', models.DateTimeField(default=datetime.datetime(2001, 1, 1, 0, 0, tzinfo=utc), editable=False)),
+ ('last_modified', models.DateTimeField(default=datetime.datetime(2001, 1, 1, 0, 0,
+ tzinfo=utc), editable=False)),
],
options={
'ordering': ('-release_date', '-version'),
@@ -171,18 +173,25 @@ class Migration(migrations.Migration):
('created', models.DateTimeField(editable=False)),
('success', models.BooleanField(default=True)),
('comments', models.TextField(blank=True, null=True)),
- ('architecture', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='releng.Architecture')),
+ ('architecture', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE,
+ to='releng.Architecture')),
('boot_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='releng.BootType')),
('bootloader', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='releng.Bootloader')),
- ('clock_choice', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='releng.ClockChoice')),
+ ('clock_choice', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE,
+ to='releng.ClockChoice')),
('filesystem', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='releng.Filesystem')),
- ('hardware_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='releng.HardwareType')),
- ('install_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='releng.InstallType')),
+ ('hardware_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE,
+ to='releng.HardwareType')),
+ ('install_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE,
+ to='releng.InstallType')),
('iso', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='releng.Iso')),
('iso_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='releng.IsoType')),
('modules', models.ManyToManyField(blank=True, null=True, to='releng.Module')),
- ('rollback_filesystem', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='rollback_test_set', to='releng.Filesystem')),
- ('rollback_modules', models.ManyToManyField(blank=True, null=True, related_name='rollback_test_set', to='releng.Module')),
+ ('rollback_filesystem', models.ForeignKey(blank=True, null=True,
+ on_delete=django.db.models.deletion.CASCADE,
+ related_name='rollback_test_set', to='releng.Filesystem')),
+ ('rollback_modules', models.ManyToManyField(blank=True, null=True, related_name='rollback_test_set',
+ to='releng.Module')),
('source', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='releng.Source')),
],
),
diff --git a/releng/migrations/0003_release_pgp_key.py b/releng/migrations/0003_release_pgp_key.py
index a211a798..3ff103c6 100644
--- a/releng/migrations/0003_release_pgp_key.py
+++ b/releng/migrations/0003_release_pgp_key.py
@@ -14,6 +14,7 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='release',
name='pgp_key',
- field=devel.fields.PGPKeyField(blank=True, help_text='consists of 40 hex digits; use `gpg --fingerprint`', max_length=40, null=True, verbose_name='PGP key fingerprint'),
+ field=devel.fields.PGPKeyField(blank=True, help_text='consists of 40 hex digits; use `gpg --fingerprint`',
+ max_length=40, null=True, verbose_name='PGP key fingerprint'),
),
]
diff --git a/releng/views.py b/releng/views.py
index 8699c5b2..f3a177d0 100644
--- a/releng/views.py
+++ b/releng/views.py
@@ -59,7 +59,7 @@ def releases_json(request):
releases = Release.objects.all()
try:
latest_version = Release.objects.filter(available=True).values_list(
- 'version', flat=True).latest()
+ 'version', flat=True).latest()
except Release.DoesNotExist:
latest_version = None
@@ -90,7 +90,7 @@ def netboot_config(request):
def netboot_info(request):
- return render(request, "releng/netboot.html",
- {'security_banner': settings.NETBOOT_SECURITY_BANNER})
+ return render(request, "releng/netboot.html",
+ {'security_banner': settings.NETBOOT_SECURITY_BANNER})
# vim: set ts=4 sw=4 et:
diff --git a/settings.py b/settings.py
index e33ee46d..5376f943 100644
--- a/settings.py
+++ b/settings.py
@@ -197,7 +197,7 @@ REBUILDERD_URL = 'https://reproducible.archlinux.org/api/v0/pkgs/list'
# Import local settings
try:
- from local_settings import *
+ from local_settings import * # noqa
except ImportError:
pass
@@ -223,9 +223,7 @@ TEMPLATES = [
# Enable the debug toolbar if requested
if DEBUG_TOOLBAR:
- MIDDLEWARE = \
- ['debug_toolbar.middleware.DebugToolbarMiddleware'] + \
- list(MIDDLEWARE)
+ MIDDLEWARE = ['debug_toolbar.middleware.DebugToolbarMiddleware'] + list(MIDDLEWARE)
INSTALLED_APPS = list(INSTALLED_APPS) + ['debug_toolbar']
diff --git a/sitemaps.py b/sitemaps.py
index 220775ca..10241516 100644
--- a/sitemaps.py
+++ b/sitemaps.py
@@ -14,9 +14,9 @@ from todolists.models import Todolist
class PackagesSitemap(Sitemap):
def items(self):
return Package.objects.normal().only(
- 'pkgname', 'last_update', 'files_last_update',
- 'repo__name', 'repo__testing', 'repo__staging',
- 'arch__name')
+ 'pkgname', 'last_update', 'files_last_update',
+ 'repo__name', 'repo__testing', 'repo__staging',
+ 'arch__name')
def lastmod(self, obj):
return obj.last_update
@@ -70,8 +70,7 @@ class SplitPackagesSitemap(Sitemap):
return obj['last_update']
def location(self, obj):
- return '/packages/%s/%s/%s/' % (
- obj['repo'].name.lower(), obj['arch'], obj['pkgbase'])
+ return f"/packages/{obj['repo'].name.lower()}/{obj['arch']}/obj['pkgbase']/"
class NewsSitemap(Sitemap):
@@ -144,24 +143,24 @@ class BaseSitemap(Sitemap):
DEFAULT_PRIORITY = 0.7
base_viewnames = (
- ('index', 1.0, 'hourly'),
- ('packages-search', 0.8, 'hourly'),
- ('page-download', 0.8, 'monthly'),
- ('page-keys', 0.8, 'weekly'),
- ('news-list', 0.7, 'weekly'),
- ('groups-list', 0.5, 'weekly'),
- ('mirror-status', 0.4, 'hourly'),
- 'page-about',
- 'page-art',
- 'page-svn',
- 'page-donate',
- 'feeds-list',
- 'mirror-list',
- 'mirror-status',
- 'mirrorlist',
- 'packages-differences',
- 'releng-release-list',
- 'visualize-index',
+ ('index', 1.0, 'hourly'),
+ ('packages-search', 0.8, 'hourly'),
+ ('page-download', 0.8, 'monthly'),
+ ('page-keys', 0.8, 'weekly'),
+ ('news-list', 0.7, 'weekly'),
+ ('groups-list', 0.5, 'weekly'),
+ ('mirror-status', 0.4, 'hourly'),
+ 'page-about',
+ 'page-art',
+ 'page-svn',
+ 'page-donate',
+ 'feeds-list',
+ 'mirror-list',
+ 'mirror-status',
+ 'mirrorlist',
+ 'packages-differences',
+ 'releng-release-list',
+ 'visualize-index',
)
def items(self):
diff --git a/todolists/migrations/0001_squashed_0002_remove_todolist_old_id.py b/todolists/migrations/0001_squashed_0002_remove_todolist_old_id.py
index 4acb0fe5..5c12b504 100644
--- a/todolists/migrations/0001_squashed_0002_remove_todolist_old_id.py
+++ b/todolists/migrations/0001_squashed_0002_remove_todolist_old_id.py
@@ -28,7 +28,8 @@ class Migration(migrations.Migration):
('created', models.DateTimeField(db_index=True)),
('last_modified', models.DateTimeField(editable=False)),
('raw', models.TextField(blank=True)),
- ('creator', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='created_todolists', to=settings.AUTH_USER_MODEL)),
+ ('creator', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT,
+ related_name='created_todolists', to=settings.AUTH_USER_MODEL)),
],
options={
'get_latest_by': 'created',
@@ -37,19 +38,22 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='TodolistPackage',
fields=[
- ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('id', models.AutoField(auto_created=True, primary_key=True,
+ serialize=False, verbose_name='ID')),
('pkgname', models.CharField(max_length=255)),
('pkgbase', models.CharField(max_length=255)),
('created', models.DateTimeField(editable=False)),
('last_modified', models.DateTimeField(editable=False)),
('removed', models.DateTimeField(blank=True, null=True)),
- ('status', models.SmallIntegerField(choices=[(0, 'Incomplete'), (1, 'Complete'), (2, 'In-progress')], default=0)),
+ ('status', models.SmallIntegerField(
+ choices=[(0, 'Incomplete'), (1, 'Complete'), (2, 'In-progress')], default=0)),
('comments', models.TextField(blank=True, null=True)),
('arch', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='main.Arch')),
('pkg', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='main.Package')),
('repo', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='main.Repo')),
('todolist', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='todolists.Todolist')),
- ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)),
+ ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL,
+ to=settings.AUTH_USER_MODEL)),
],
options={
'get_latest_by': 'created',
diff --git a/todolists/models.py b/todolists/models.py
index c89d09b6..caeccff9 100644
--- a/todolists/models.py
+++ b/todolists/models.py
@@ -39,9 +39,9 @@ class Todolist(models.Model):
def packages(self):
if not hasattr(self, '_packages'):
self._packages = self.todolistpackage_set.filter(
- removed__isnull=True).select_related(
- 'pkg', 'repo', 'arch', 'user__userprofile').order_by(
- 'pkgname', 'arch')
+ removed__isnull=True).select_related(
+ 'pkg', 'repo', 'arch', 'user__userprofile').order_by(
+ 'pkgname', 'arch')
return self._packages
diff --git a/todolists/tests/test_models.py b/todolists/tests/test_models.py
index 4e629f37..52b11df2 100644
--- a/todolists/tests/test_models.py
+++ b/todolists/tests/test_models.py
@@ -37,9 +37,9 @@ class TestTodolist(TestCase):
def test_packages(self):
pkg = Package.objects.first()
todopkg = TodolistPackage.objects.create(pkg=pkg, pkgname=pkg.pkgname,
- pkgbase=pkg.pkgbase, arch=pkg.arch,
- repo=pkg.repo, user=self.user,
- todolist=self.todolist)
+ pkgbase=pkg.pkgbase, arch=pkg.arch,
+ repo=pkg.repo, user=self.user,
+ todolist=self.todolist)
pkgs = self.todolist.packages()
self.assertEqual(len(pkgs), 1)
self.assertEqual(pkgs[0], todopkg)
diff --git a/todolists/tests/test_views.py b/todolists/tests/test_views.py
index 8c605bc3..bebb8d1a 100644
--- a/todolists/tests/test_views.py
+++ b/todolists/tests/test_views.py
@@ -46,9 +46,8 @@ class TestTodolistAdmin(TestCase):
password)
self.client.post('/login/', {
- 'username': self.user.username,
- 'password': password
- })
+ 'username': self.user.username,
+ 'password': password})
def tearDown(self):
Todolist.objects.all().delete()
diff --git a/todolists/urls.py b/todolists/urls.py
index 91f3712f..78f833bd 100644
--- a/todolists/urls.py
+++ b/todolists/urls.py
@@ -2,7 +2,7 @@ from django.conf.urls import url
from django.contrib.auth.decorators import permission_required
from .views import (view, view_json, add, edit, flag,
- list_pkgbases, DeleteTodolist, TodolistListView)
+ list_pkgbases, DeleteTodolist, TodolistListView)
urlpatterns = [
url(r'^$', TodolistListView.as_view(), name='todolist-list'),
diff --git a/todolists/utils.py b/todolists/utils.py
index c090520f..6dc68077 100644
--- a/todolists/utils.py
+++ b/todolists/utils.py
@@ -21,7 +21,7 @@ SELECT todolist_id, count(*), SUM(CASE WHEN status = %s THEN 1 ELSE 0 END)
def get_annotated_todolists(incomplete_only=False):
lists = Todolist.objects.all().defer('raw').select_related(
- 'creator').order_by('-created')
+ 'creator').order_by('-created')
lookup = todo_counts()
# tag each list with package counts
@@ -32,7 +32,7 @@ def get_annotated_todolists(incomplete_only=False):
todolist.incomplete_count = counts[0] - counts[1]
if incomplete_only:
- lists = [l for l in lists if l.incomplete_count > 0]
+ lists = [lst for lst in lists if lst.incomplete_count > 0]
else:
lists = sorted(lists, key=lambda todolist: todolist.incomplete_count == 0)
return lists
@@ -42,9 +42,9 @@ def attach_staging(packages, list_id):
'''Look for any staging version of the packages provided and attach them
to the 'staging' attribute on each package if found.'''
pkgnames = TodolistPackage.objects.filter(
- todolist_id=list_id).values('pkgname')
+ todolist_id=list_id).values('pkgname')
staging_pkgs = Package.objects.normal().filter(repo__staging=True,
- pkgname__in=pkgnames)
+ pkgname__in=pkgnames)
# now build a lookup dict to attach to the correct package
lookup = {(p.pkgname, p.arch): p for p in staging_pkgs}
diff --git a/todolists/views.py b/todolists/views.py
index fdc5cfc6..4a0df38d 100644
--- a/todolists/views.py
+++ b/todolists/views.py
@@ -5,7 +5,7 @@ from django import forms
from django.http import HttpResponse
from django.core.mail import send_mail
from django.shortcuts import (get_list_or_404, get_object_or_404,
- redirect, render)
+ redirect, render)
from django.db import transaction
from django.views.decorators.cache import never_cache
from django.views.generic import DeleteView, ListView
@@ -21,16 +21,16 @@ from .utils import get_annotated_todolists, attach_staging
class TodoListForm(forms.ModelForm):
raw = forms.CharField(label='Packages', required=False,
- help_text='(one per line)',
- widget=forms.Textarea(attrs={'rows': '20', 'cols': '60'}))
+ help_text='(one per line)',
+ widget=forms.Textarea(attrs={'rows': '20', 'cols': '60'}))
def package_names(self):
return {s.strip() for s in self.cleaned_data['raw'].split("\n")}
def packages(self):
return Package.objects.normal().filter(
- pkgname__in=self.package_names(),
- repo__testing=False, repo__staging=False).order_by('arch')
+ pkgname__in=self.package_names(),
+ repo__testing=False, repo__staging=False).order_by('arch')
class Meta:
model = Todolist
@@ -60,7 +60,7 @@ def flag(request, slug, pkg_id):
def view(request, slug):
todolist = get_object_or_404(Todolist, slug=slug)
svn_roots = Repo.objects.values_list(
- 'svn_root', flat=True).order_by().distinct()
+ 'svn_root', flat=True).order_by().distinct()
# we don't hold onto the result, but the objects are the same here,
# so accessing maintainers in the template is now cheap
attach_maintainers(todolist.packages())
@@ -81,9 +81,9 @@ def list_pkgbases(request, slug, svn_root):
todolist = get_object_or_404(Todolist, slug=slug)
repos = get_list_or_404(Repo, svn_root=svn_root)
pkgbases = TodolistPackage.objects.values_list(
- 'pkgbase', flat=True).filter(
- todolist=todolist, repo__in=repos, removed__isnull=True).order_by(
- 'pkgbase').distinct()
+ 'pkgbase', flat=True).filter(
+ todolist=todolist, repo__in=repos, removed__isnull=True).order_by(
+ 'pkgbase').distinct()
return HttpResponse('\n'.join(pkgbases), content_type='text/plain')
@@ -108,10 +108,10 @@ def add(request):
form = TodoListForm()
page_dict = {
- 'title': 'Add Todo List',
- 'description': '',
- 'form': form,
- 'submit_text': 'Create List'
+ 'title': 'Add Todo List',
+ 'description': '',
+ 'form': form,
+ 'submit_text': 'Create List'
}
return render(request, 'general_form.html', page_dict)
@@ -128,13 +128,13 @@ def edit(request, slug):
return redirect(todo_list)
else:
form = TodoListForm(instance=todo_list,
- initial={'packages': todo_list.raw})
+ initial={'packages': todo_list.raw})
page_dict = {
- 'title': 'Edit Todo List: %s' % todo_list.name,
- 'description': '',
- 'form': form,
- 'submit_text': 'Save List'
+ 'title': f'Edit Todo List: {todo_list.name}',
+ 'description': '',
+ 'form': form,
+ 'submit_text': 'Save List'
}
return render(request, 'general_form.html', page_dict)
@@ -171,7 +171,7 @@ def create_todolist_packages(form, creator=None):
to_remove.add(todo_pkg.pk)
TodolistPackage.objects.filter(
- pk__in=to_remove).update(removed=timestamp)
+ pk__in=to_remove).update(removed=timestamp)
# Add (or mark unremoved) any packages in the new packages list
todo_pkgs = []
@@ -183,10 +183,10 @@ def create_todolist_packages(form, creator=None):
'repo': package.repo,
}
todo_pkg, created = TodolistPackage.objects.get_or_create(
- todolist=todolist,
- pkgname=package.pkgname,
- arch=package.arch,
- defaults=defaults)
+ todolist=todolist,
+ pkgname=package.pkgname,
+ arch=package.arch,
+ defaults=defaults)
if created:
todo_pkgs.append(todo_pkg)
else:
@@ -226,10 +226,10 @@ def send_todolist_emails(todo_list, new_packages):
}
template = loader.get_template('todolists/email_notification.txt')
send_mail('Packages added to todo list \'%s\'' % todo_list.name,
- template.render(ctx),
- 'Arch Website Notification <nobody@archlinux.org>',
- [maint],
- fail_silently=True)
+ template.render(ctx),
+ 'Arch Website Notification <nobody@archlinux.org>',
+ [maint],
+ fail_silently=True)
class TodoListJSONEncoder(PackageJSONEncoder):
diff --git a/urls.py b/urls.py
index 1bfbc7f4..b676b7b0 100644
--- a/urls.py
+++ b/urls.py
@@ -60,7 +60,8 @@ feeds_patterns = [
url(r'^packages/(added|removed)/$', cache_page(313)(PackageUpdatesFeed())),
url(r'^packages/(added|removed)/(?P<arch>[A-z0-9]+)/$', cache_page(313)(PackageUpdatesFeed())),
url(r'^packages/(added|removed)/all/(?P<repo>[A-z0-9\-]+)/$', cache_page(313)(PackageUpdatesFeed())),
- url(r'^packages/(added|removed)/(?P<arch>[A-z0-9]+)/(?P<repo>[A-z0-9\-]+)/$', cache_page(313)(PackageUpdatesFeed())),
+ url(r'^packages/(added|removed)/(?P<arch>[A-z0-9]+)/(?P<repo>[A-z0-9\-]+)/$',
+ cache_page(313)(PackageUpdatesFeed())),
url(r'^packages/(?P<arch>[A-z0-9]+)/$', cache_page(313)(PackageFeed())),
url(r'^packages/all/(?P<repo>[A-z0-9\-]+)/$', cache_page(313)(PackageFeed())),
url(r'^packages/(?P<arch>[A-z0-9]+)/(?P<repo>[A-z0-9\-]+)/$', cache_page(313)(PackageFeed())),
@@ -76,16 +77,16 @@ urlpatterns.extend([
# Includes and other remaining stuff
urlpatterns.extend([
- url(r'^admin/', admin.site.urls),
- url(r'^devel/', include(devel.urls)),
- url(r'^feeds/', include(feeds_patterns)),
- url(r'^groups/', include(packages.urls_groups)),
- url(r'^mirrorlist/',include(mirrors.urls_mirrorlist)),
- url(r'^mirrors/', include(mirrors.urls)),
- url(r'^news/', include(news.urls)),
- url(r'^packages/', include(packages.urls)),
- url(r'^releng/', include(releng.urls)),
- url(r'^todo/', include(todolists.urls)),
+ url(r'^admin/', admin.site.urls),
+ url(r'^devel/', include(devel.urls)),
+ url(r'^feeds/', include(feeds_patterns)),
+ url(r'^groups/', include(packages.urls_groups)),
+ url(r'^mirrorlist/', include(mirrors.urls_mirrorlist)),
+ url(r'^mirrors/', include(mirrors.urls)),
+ url(r'^news/', include(news.urls)),
+ url(r'^packages/', include(packages.urls)),
+ url(r'^releng/', include(releng.urls)),
+ url(r'^todo/', include(todolists.urls)),
url(r'^visualize/', include(visualize.urls)),
url(r'^opensearch/packages/$', packages.views.opensearch, name='opensearch-packages'),
url(r'^opensearch/packages/suggest$', packages.views.opensearch_suggest, name='opensearch-packages-suggest'),
@@ -116,6 +117,7 @@ if settings.DEBUG_TOOLBAR:
path('__debug__/', include(debug_toolbar.urls)),
])
+
# displays all archweb urls
def show_urls(urllist=urlpatterns, depth=0): # pragma: no cover
for entry in urllist:
diff --git a/visualize/views.py b/visualize/views.py
index 27b2e03f..991dac29 100644
--- a/visualize/views.py
+++ b/visualize/views.py
@@ -14,10 +14,10 @@ def index(request):
def arch_repo_data():
qs = Package.objects.select_related().values(
- 'arch__name', 'repo__name').annotate(
- count=Count('pk'), csize=Sum('compressed_size'),
- isize=Sum('installed_size'),
- flagged=Count('flag_date')).order_by()
+ 'arch__name', 'repo__name').annotate(
+ count=Count('pk'), csize=Sum('compressed_size'),
+ isize=Sum('installed_size'),
+ flagged=Count('flag_date')).order_by()
arches = Arch.objects.values_list('name', flat=True)
repos = Repo.objects.values_list('name', flat=True)
@@ -52,8 +52,8 @@ def arch_repo_data():
repo_groups[repo]['data'].append(values)
data = {
- 'by_arch': { 'name': 'Architectures', 'data': list(arch_groups.values()) },
- 'by_repo': { 'name': 'Repositories', 'data': list(repo_groups.values()) },
+ 'by_arch': {'name': 'Architectures', 'data': list(arch_groups.values())},
+ 'by_repo': {'name': 'Repositories', 'data': list(repo_groups.values())},
}
return data