From 6e2d26bb88aea654c6e5975e7344351e66ca00d3 Mon Sep 17 00:00:00 2001
From: Pierre-Yves Chibon <pingou@pingoured.fr>
Date: Apr 26 2016 13:47:08 +0000
Subject: [PATCH 1/3] Enforce that each widget has a position that must be in 'left', 'right' or 'both'


---

diff --git a/hubs/widgets/__init__.py b/hubs/widgets/__init__.py
index 551876a..2e72e00 100755
--- a/hubs/widgets/__init__.py
+++ b/hubs/widgets/__init__.py
@@ -57,6 +57,13 @@ def validate_registry(registry):
         if not callable(module.template.render):
             raise TypeError('%r\'s template.render not callable' % module)
 
+        if not hasattr(module, 'position'):
+            raise AttributeError('%r has not "position" function' % module)
+        if module.position not in ['left', 'right', 'both']:
+            raise TypeError(
+                '%r\'s "position" is not: `left`, `right` or `both`'
+                % module)
+
         if not hasattr(module, 'data'):
             raise AttributeError('%r has not "data" function' % module)
         if not callable(module.data):

From 4c983f4c868a2f2fbef3c14e1f09c1c39b3ea58b Mon Sep 17 00:00:00 2001
From: Pierre-Yves Chibon <pingou@pingoured.fr>
Date: Apr 26 2016 13:47:08 +0000
Subject: [PATCH 2/3] Set a position to each existing widget


---

diff --git a/hubs/widgets/about.py b/hubs/widgets/about.py
index 061ec6e..2383081 100755
--- a/hubs/widgets/about.py
+++ b/hubs/widgets/about.py
@@ -8,7 +8,7 @@ import hubs.validators as validators
 
 chrome = panel("<span class='glyphicon glyphicon-info-sign' aria-hidden='true'></span> About")
 template = templating.environment.get_template('templates/about.html')
-
+position = 'both'
 
 @argument(name="text", default="I am a Fedora user, and this is my about",
           validator=validators.text,
diff --git a/hubs/widgets/badges.py b/hubs/widgets/badges.py
index f65c4fb..4ddbb3d 100755
--- a/hubs/widgets/badges.py
+++ b/hubs/widgets/badges.py
@@ -11,7 +11,7 @@ import hubs.validators as validators
 from hubs.widgets.chrome import panel
 chrome = panel("Badges")
 template = templating.environment.get_template('templates/badges.html')
-
+position = 'right'
 
 @argument(name="username",
           default=None,
diff --git a/hubs/widgets/bugzilla.py b/hubs/widgets/bugzilla.py
index 2576963..856f975 100644
--- a/hubs/widgets/bugzilla.py
+++ b/hubs/widgets/bugzilla.py
@@ -9,7 +9,7 @@ from hubs.hinting import hint
 
 chrome = panel("Bugzilla: Issues")
 template = templating.environment.get_template('templates/bugzilla.html')
-
+position = 'right'
 
 @argument(name="username",
           default=None,
diff --git a/hubs/widgets/dummy.py b/hubs/widgets/dummy.py
index c6fbb90..f25f65a 100755
--- a/hubs/widgets/dummy.py
+++ b/hubs/widgets/dummy.py
@@ -7,6 +7,7 @@ import hubs.validators as validators
 
 chrome = panel("This is a dummy widget")
 template = templating.environment.get_template('templates/dummy.html')
+position = 'both'
 
 @argument(name="text", default="Lorem ipsum dolor...",
           validator=validators.text,
diff --git a/hubs/widgets/fedmsgstats.py b/hubs/widgets/fedmsgstats.py
index d06f398..9cd15fd 100755
--- a/hubs/widgets/fedmsgstats.py
+++ b/hubs/widgets/fedmsgstats.py
@@ -14,6 +14,7 @@ config = fedmsg.config.load_config()
 
 chrome = panel()
 template = templating.environment.get_template('templates/fedmsgstats.html')
+position = 'both'
 
 
 def data(session, widget, username):
diff --git a/hubs/widgets/feed.py b/hubs/widgets/feed.py
index 2e61dc7..282a400 100755
--- a/hubs/widgets/feed.py
+++ b/hubs/widgets/feed.py
@@ -38,7 +38,7 @@ paths = fmn.lib.load_rules(root='fmn.rules')
 #from hubs.widgets.chrome import panel
 #chrome = panel()
 template = templating.environment.get_template('templates/feed.html')
-
+position = 'left'
 
 def apply_markup(match):
     markup = match['subtitle']
diff --git a/hubs/widgets/github_pr.py b/hubs/widgets/github_pr.py
index 5ee081a..b2d1788 100755
--- a/hubs/widgets/github_pr.py
+++ b/hubs/widgets/github_pr.py
@@ -15,6 +15,7 @@ log = logging.getLogger(__name__)
 
 chrome = panel("Github: Pull Requests")
 template = templating.environment.get_template('templates/github_pr.html')
+position = 'right'
 
 
 @argument(name="display_number",
diff --git a/hubs/widgets/githubissues.py b/hubs/widgets/githubissues.py
index 35536f7..2bd6c87 100755
--- a/hubs/widgets/githubissues.py
+++ b/hubs/widgets/githubissues.py
@@ -7,6 +7,7 @@ import requests
 
 chrome = panel("Github: Newest Open Tickets")
 template = templating.environment.get_template('templates/githubissues.html')
+position = 'right'
 
 
 @argument(name="repo",
diff --git a/hubs/widgets/linechart.py b/hubs/widgets/linechart.py
index ee47d85..2c5562f 100755
--- a/hubs/widgets/linechart.py
+++ b/hubs/widgets/linechart.py
@@ -10,6 +10,7 @@ config = fedmsg.config.load_config()
 from hubs.widgets.chrome import panel
 chrome = panel("Weekly Activity")
 template = templating.environment.get_template('templates/linechart.html')
+position = 'left'
 
 
 @argument(name="username",
diff --git a/hubs/widgets/meetings.py b/hubs/widgets/meetings.py
index 3a40832..5812f94 100755
--- a/hubs/widgets/meetings.py
+++ b/hubs/widgets/meetings.py
@@ -55,6 +55,7 @@ footer_template = templating.environment.get_template('templates/meeting_footer.
 chrome = panel(title = 'Reminders', key='meetings', footer_template=footer_template)
 templating.environment.filters['humanize'] = lambda d: arrow.get(d).humanize()
 template = templating.environment.get_template('templates/meetings.html')
+position = 'both'
 
 
 @argument(name="calendar",
diff --git a/hubs/widgets/pagure_pr.py b/hubs/widgets/pagure_pr.py
index 350291d..cdb8365 100755
--- a/hubs/widgets/pagure_pr.py
+++ b/hubs/widgets/pagure_pr.py
@@ -11,6 +11,7 @@ pagure_url = "https://pagure.io/api/0"
 
 chrome = panel("Newest Open Pull Requests on Pagure")
 template = templating.environment.get_template('templates/pagure_pr.html')
+position = 'right'
 
 
 @argument(name="repo",
diff --git a/hubs/widgets/pagureissues.py b/hubs/widgets/pagureissues.py
index ab13903..3975253 100755
--- a/hubs/widgets/pagureissues.py
+++ b/hubs/widgets/pagureissues.py
@@ -9,6 +9,7 @@ pagure_url = "https://pagure.io/api/0"
 
 chrome = panel("Newest Open Tickets on Pagure")
 template = templating.environment.get_template('templates/pagureissues.html')
+position = 'right'
 
 
 @argument(name="repo",
diff --git a/hubs/widgets/rules.py b/hubs/widgets/rules.py
index 4b17931..d0bfad7 100755
--- a/hubs/widgets/rules.py
+++ b/hubs/widgets/rules.py
@@ -8,6 +8,7 @@ from hubs import validators
 
 chrome = panel()
 template = templating.environment.get_template('templates/rules.html')
+position = 'both'
 
 
 @argument(name='link', default=None,
diff --git a/hubs/widgets/stats.py b/hubs/widgets/stats.py
index 3b784e3..319e287 100755
--- a/hubs/widgets/stats.py
+++ b/hubs/widgets/stats.py
@@ -8,6 +8,7 @@ import flask
 
 chrome = panel()
 template = templating.environment.get_template('templates/stats.html')
+position = 'right'
 
 
 def data(session, widget):
diff --git a/hubs/widgets/sticky.py b/hubs/widgets/sticky.py
index 4176c97..55cc6a1 100755
--- a/hubs/widgets/sticky.py
+++ b/hubs/widgets/sticky.py
@@ -7,6 +7,7 @@ import hubs.validators as validators
 
 chrome = panel(title='Sticky Note', klass="card-info")
 template = templating.environment.get_template('templates/sticky.html')
+position = 'both'
 
 
 @argument(name="text", default="Lorem ipsum dolor...",
diff --git a/hubs/widgets/subscriptions.py b/hubs/widgets/subscriptions.py
index 6576516..82fce66 100755
--- a/hubs/widgets/subscriptions.py
+++ b/hubs/widgets/subscriptions.py
@@ -16,6 +16,7 @@ import flask
 
 chrome = panel('Hubs', key='associations')
 template = templating.environment.get_template('templates/subscriptions.html')
+position = 'right'
 
 
 @argument(name="username",
diff --git a/hubs/widgets/workflow/pendingacls.py b/hubs/widgets/workflow/pendingacls.py
index 6f0e678..8538999 100644
--- a/hubs/widgets/workflow/pendingacls.py
+++ b/hubs/widgets/workflow/pendingacls.py
@@ -12,6 +12,7 @@ from hubs.widgets.chrome import panel
 chrome = panel('Pending ACL Requests', key='pending_acls')
 # TODO -- add approve/deny buttons or just link through to pkgdb
 template = templating.environment.get_template('templates/workflow/pendingacls.html')
+position = 'right'
 
 
 @argument(name="username",
diff --git a/hubs/widgets/workflow/updates2stable.py b/hubs/widgets/workflow/updates2stable.py
index 668fcc7..675d793 100644
--- a/hubs/widgets/workflow/updates2stable.py
+++ b/hubs/widgets/workflow/updates2stable.py
@@ -12,6 +12,7 @@ chrome = panel('Updates Ready for Stable', key='updates')
 # TODO -- add approve/deny buttons or just link through to pkgdb
 template = templating.environment.get_template(
     'templates/workflow/updates2stable.html')
+position = 'right'
 
 # TODO - the bodhi api exposes a new flag we can use instead of scraping comments...
 giveaway = 'can be pushed to stable now'

From c16ea2ae9932dc25a5ca73eb7503d577abe1c8d1 Mon Sep 17 00:00:00 2001
From: Pierre-Yves Chibon <pingou@pingoured.fr>
Date: Apr 26 2016 13:47:08 +0000
Subject: [PATCH 3/3] Code style fixes


---

diff --git a/hubs/utils.py b/hubs/utils.py
index 6eb43b7..ed00d80 100755
--- a/hubs/utils.py
+++ b/hubs/utils.py
@@ -11,8 +11,10 @@ log = logging.getLogger(__name__)
 
 
 def markup(text):
-    return markdown.markdown(text, safe_mode="replace",
-                             html_replacement_text="--RAW HTML NOT ALLOWED--")
+    return markdown.markdown(
+        text,
+        safe_mode="replace",
+        html_replacement_text="--RAW HTML NOT ALLOWED--")
 
 
 def username2avatar(username, s=312):
@@ -29,6 +31,7 @@ def username2avatar(username, s=312):
 def commas(numeric):
     return "{:,}".format(numeric)
 
+
 def github_repos(token, username):
     log.info("Finding github repos for %r" % username)
     tmpl = "https://api.github.com/users/{username}/repos?per_page=100"
diff --git a/hubs/validators.py b/hubs/validators.py
index 9c2c276..f6da8dc 100755
--- a/hubs/validators.py
+++ b/hubs/validators.py
@@ -6,29 +6,36 @@ import hubs.models
 def required(session, value):
     return bool(value)
 
+
 def text(session, value):
     return kitchen.text.converters.to_unicode(value)
 
+
 def integer(session, value):
     return int(value)
 
+
 def link(session, value):
     # TODO -- verify that this is actually a link
     return value
 
+
 def username(session, value):
     openid = 'http://%s.id.fedoraproject.org/' % value
     return not hubs.models.User.by_openid(session, openid) is None
 
+
 def github_organization(session, value):
     # TODO -- implement this.
     return True
 
+
 def fmn_context(session, value):
     # TODO get this from the fedmsg config.
     return value in [
         'irc', 'email', 'android', 'desktop', 'hubs',
     ]
 
+
 def pagure_repo(session, value):
     return value

