From b5c72da91817fb50d276e22a0c708dc326fb5b3e Mon Sep 17 00:00:00 2001 From: "Brian S. Stephan" Date: Sat, 11 Feb 2017 08:15:02 -0600 Subject: [PATCH 1/9] prospector: disable PEP257 D203 for whatever reason both it and D211 exist, and i'm choosing D211 bss/dr.botzo#17 --- .prospector.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.prospector.yaml b/.prospector.yaml index 4dcd596..e79b751 100644 --- a/.prospector.yaml +++ b/.prospector.yaml @@ -15,3 +15,6 @@ pylint: pep8: options: max-line-length: 120 +pep257: + disable: + - D203 From 4740cd780829f7d4816cbbfc7952cb48e4def237 Mon Sep 17 00:00:00 2001 From: "Brian S. Stephan" Date: Sat, 11 Feb 2017 08:24:08 -0600 Subject: [PATCH 2/9] prospector: turn up strictness let's start with some serious code quality refactoring later, but this is at least setting the underpinnings bss/dr.botzo#17 --- .prospector.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.prospector.yaml b/.prospector.yaml index e79b751..838b437 100644 --- a/.prospector.yaml +++ b/.prospector.yaml @@ -1,5 +1,5 @@ doc-warnings: true -strictness: medium +strictness: high ignore-paths: - migrations ignore-patterns: From cd31bbb489dab9d013e5dcfa620803ed247fe28b Mon Sep 17 00:00:00 2001 From: "Brian S. Stephan" Date: Sat, 11 Feb 2017 08:27:55 -0600 Subject: [PATCH 3/9] facts: code quality changes bss/dr.botzo#17 --- facts/__init__.py | 7 +++++++ facts/admin.py | 1 + facts/ircplugin.py | 7 ------- facts/models.py | 10 ++-------- 4 files changed, 10 insertions(+), 15 deletions(-) diff --git a/facts/__init__.py b/facts/__init__.py index e69de29..07e15d3 100644 --- a/facts/__init__.py +++ b/facts/__init__.py @@ -0,0 +1,7 @@ +"""Facts allows storage of arbitrarily defined sets of strings. + +The "fact" part is tongue-in-cheek, you can put random options for a decision, +roulette style game modes, 8-ball type functionality, and total falsehoods +in here too. When fact categories are queried, a random one is returned if +you don't know what you're looking for. +""" diff --git a/facts/admin.py b/facts/admin.py index 7764b7f..a971e69 100644 --- a/facts/admin.py +++ b/facts/admin.py @@ -1,3 +1,4 @@ +"""Admin interface for the facts app.""" from django.contrib import admin from facts.models import Fact, FactCategory diff --git a/facts/ircplugin.py b/facts/ircplugin.py index 2f0795f..d964e34 100644 --- a/facts/ircplugin.py +++ b/facts/ircplugin.py @@ -1,5 +1,4 @@ """IRC plugin for retrieval of facts.""" - import logging from irc.client import NickMask @@ -7,17 +6,14 @@ from irc.client import NickMask from ircbot.lib import Plugin, has_permission from facts.models import Fact, FactCategory - log = logging.getLogger('facts.ircplugin') class Facts(Plugin): - """Present facts to IRC.""" def start(self): """Set up the handlers.""" - self.connection.reactor.add_global_regex_handler(['pubmsg', 'privmsg'], r'^!facts\s+add\s+(\S+)\s+(.*)$', self.handle_add_fact, -20) self.connection.reactor.add_global_regex_handler(['pubmsg', 'privmsg'], r'^!facts\s+(\S+)(\s+(.*)$|$)', @@ -27,7 +23,6 @@ class Facts(Plugin): def stop(self): """Tear down handlers.""" - self.connection.reactor.remove_global_regex_handler(['pubmsg', 'privmsg'], self.handle_add_fact) self.connection.reactor.remove_global_regex_handler(['pubmsg', 'privmsg'], self.handle_facts) @@ -35,7 +30,6 @@ class Facts(Plugin): def handle_facts(self, connection, event, match): """Respond to the facts command with desired fact.""" - category = match.group(1) regex = None if match.group(2) != '': @@ -53,7 +47,6 @@ class Facts(Plugin): def handle_add_fact(self, connection, event, match): """Add a new fact to the database.""" - category_name = match.group(1) fact_text = match.group(2) diff --git a/facts/models.py b/facts/models.py index fd6de05..dd2a60f 100644 --- a/facts/models.py +++ b/facts/models.py @@ -1,37 +1,33 @@ """Store "facts".""" - import logging import random from django.db import models - log = logging.getLogger('facts.models') class FactCategory(models.Model): - """Define categories for facts.""" name = models.CharField(max_length=200, unique=True) show_source = models.BooleanField(default=False) class Meta: + """Meta options.""" + verbose_name_plural = 'fact categories' def __str__(self): """String representation.""" - return "{0:s}".format(self.name) class FactManager(models.Manager): - """Queries against Fact.""" def random_fact(self, category, regex=None): """Get a random fact from the database.""" - try: fact_category = FactCategory.objects.get(name=category) except FactCategory.DoesNotExist: @@ -48,7 +44,6 @@ class FactManager(models.Manager): class Fact(models.Model): - """Define facts.""" fact = models.TextField() @@ -60,5 +55,4 @@ class Fact(models.Model): def __str__(self): """String representation.""" - return "{0:s} - {1:s}".format(self.category.name, self.fact) From 36e2de5dfdaa98a1ee3b38a29e4d878c1f4be5df Mon Sep 17 00:00:00 2001 From: "Brian S. Stephan" Date: Sat, 11 Feb 2017 08:44:07 -0600 Subject: [PATCH 4/9] facts: provide Fact as an inline on FactCategory closes bss/dr.botzo#14 --- facts/admin.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/facts/admin.py b/facts/admin.py index a971e69..9b4f26f 100644 --- a/facts/admin.py +++ b/facts/admin.py @@ -4,5 +4,17 @@ from django.contrib import admin from facts.models import Fact, FactCategory +class FactInline(admin.TabularInline): + """Inline admin form for facts, for inclusion in fact categories.""" + + model = Fact + + +class FactCategoryAdmin(admin.ModelAdmin): + """Admin pages for the FactCategory model.""" + + inlines = [FactInline] + + admin.site.register(Fact) -admin.site.register(FactCategory) +admin.site.register(FactCategory, FactCategoryAdmin) From 4bf0c7e260f934eb9830866a1e00fecf803ccd6c Mon Sep 17 00:00:00 2001 From: "Brian S. Stephan" Date: Sat, 11 Feb 2017 09:21:18 -0600 Subject: [PATCH 5/9] facts: boolean to display facts items in view carried over from the choices functionality that always does this, make this an option for the FactCategory for when we have views bss/dr.botzo#15 --- .../0006_factcategory_show_all_entries.py | 20 +++++++++++++++++++ facts/models.py | 1 + 2 files changed, 21 insertions(+) create mode 100644 facts/migrations/0006_factcategory_show_all_entries.py diff --git a/facts/migrations/0006_factcategory_show_all_entries.py b/facts/migrations/0006_factcategory_show_all_entries.py new file mode 100644 index 0000000..b324817 --- /dev/null +++ b/facts/migrations/0006_factcategory_show_all_entries.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.5 on 2017-02-11 15:00 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('facts', '0005_auto_20150814_1653'), + ] + + operations = [ + migrations.AddField( + model_name='factcategory', + name='show_all_entries', + field=models.BooleanField(default=False), + ), + ] diff --git a/facts/models.py b/facts/models.py index dd2a60f..5a70e21 100644 --- a/facts/models.py +++ b/facts/models.py @@ -11,6 +11,7 @@ class FactCategory(models.Model): """Define categories for facts.""" name = models.CharField(max_length=200, unique=True) + show_all_entries = models.BooleanField(default=False) show_source = models.BooleanField(default=False) class Meta: From 368dfd4a8327bb88ed7758875a861f29c01aee0d Mon Sep 17 00:00:00 2001 From: "Brian S. Stephan" Date: Sat, 11 Feb 2017 09:22:32 -0600 Subject: [PATCH 6/9] facts: refactor random_fact onto FactCategory since the views will have a FactCategory, not a Fact, we'll move the convenience random_fact() there and use it in the FactManager bss/dr.botzo#15 --- facts/models.py | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/facts/models.py b/facts/models.py index 5a70e21..63b1225 100644 --- a/facts/models.py +++ b/facts/models.py @@ -23,18 +23,9 @@ class FactCategory(models.Model): """String representation.""" return "{0:s}".format(self.name) - -class FactManager(models.Manager): - """Queries against Fact.""" - - def random_fact(self, category, regex=None): - """Get a random fact from the database.""" - try: - fact_category = FactCategory.objects.get(name=category) - except FactCategory.DoesNotExist: - return None - - facts = Fact.objects.filter(category=fact_category) + def random_fact(self, regex=None): + """Get a random fact in this category.""" + facts = self.fact_set.all() if regex: facts = facts.filter(fact__iregex=regex) @@ -44,6 +35,19 @@ class FactManager(models.Manager): return None +class FactManager(models.Manager): + """Queries against Fact.""" + + def random_fact(self, category, regex=None): + """Get a random fact from the database.""" + try: + factcategory = FactCategory.objects.get(name=category) + except FactCategory.DoesNotExist: + return None + + return factcategory.random_fact(regex) + + class Fact(models.Model): """Define facts.""" From fb04732ec3156f24797dd6fa674b7f782b246406 Mon Sep 17 00:00:00 2001 From: "Brian S. Stephan" Date: Sat, 11 Feb 2017 09:32:30 -0600 Subject: [PATCH 7/9] facts: recreate the choices experience in facts recreates the choices view in facts, allowing for display of any fact category in the system, and providing a random item from it bss/dr.botzo#15 --- dr_botzo/urls.py | 1 + facts/templates/facts/base.html | 4 +++ .../templates/facts/factcategory_detail.html | 11 ++++++++ facts/templates/facts/index.html | 11 ++++++++ facts/urls.py | 9 +++++++ facts/views.py | 26 +++++++++++++++++++ static/css/facts.css | 4 +++ templates/base.html | 1 + 8 files changed, 67 insertions(+) create mode 100644 facts/templates/facts/base.html create mode 100644 facts/templates/facts/factcategory_detail.html create mode 100644 facts/templates/facts/index.html create mode 100644 facts/urls.py create mode 100644 facts/views.py create mode 100644 static/css/facts.css diff --git a/dr_botzo/urls.py b/dr_botzo/urls.py index ce22036..145ecd8 100644 --- a/dr_botzo/urls.py +++ b/dr_botzo/urls.py @@ -14,6 +14,7 @@ urlpatterns = [ url(r'^choices/', include('choices.urls')), url(r'^dispatch/', include('dispatch.urls')), + url(r'^itemsets/', include('facts.urls')), url(r'^karma/', include('karma.urls')), url(r'^markov/', include('markov.urls')), url(r'^races/', include('races.urls')), diff --git a/facts/templates/facts/base.html b/facts/templates/facts/base.html new file mode 100644 index 0000000..9abceb2 --- /dev/null +++ b/facts/templates/facts/base.html @@ -0,0 +1,4 @@ +{% extends 'base.html' %} +{% block extra_media %}{% load static %} + +{% endblock %} diff --git a/facts/templates/facts/factcategory_detail.html b/facts/templates/facts/factcategory_detail.html new file mode 100644 index 0000000..a149ca9 --- /dev/null +++ b/facts/templates/facts/factcategory_detail.html @@ -0,0 +1,11 @@ +{% extends 'facts/base.html' %} + +{% block title %}item set: {{ factcategory.name }}{% endblock %} + +{% block content %} +

{{ factcategory.name }}

+

{{ factcategory.random_fact.fact }}

+ {% if factcategory.show_all_entries %} +
Items: {{ facts|join:", " }}
+ {% endif %} +{% endblock %} diff --git a/facts/templates/facts/index.html b/facts/templates/facts/index.html new file mode 100644 index 0000000..72efb77 --- /dev/null +++ b/facts/templates/facts/index.html @@ -0,0 +1,11 @@ +{% extends 'facts/base.html' %} + +{% block title %}item sets{% endblock %} + +{% block content %} + +{% endblock %} diff --git a/facts/urls.py b/facts/urls.py new file mode 100644 index 0000000..826a334 --- /dev/null +++ b/facts/urls.py @@ -0,0 +1,9 @@ +"""URL patterns for the facts web views.""" +from django.conf.urls import url + +from facts.views import index, factcategory_detail + +urlpatterns = [ + url(r'^$', index, name='facts_index'), + url(r'^(?P.+)/$', factcategory_detail, name='facts_factcategory_detail'), +] diff --git a/facts/views.py b/facts/views.py new file mode 100644 index 0000000..3dfb112 --- /dev/null +++ b/facts/views.py @@ -0,0 +1,26 @@ +"""Display fact categories.""" +import logging + +from django.shortcuts import get_object_or_404, render + +from facts.models import FactCategory + +log = logging.getLogger(__name__) + + +def index(request): + """Display a simple list of the fact categories, for the moment.""" + factcategories = FactCategory.objects.all() + + return render(request, 'facts/index.html', {'factcategories': factcategories}) + + +def factcategory_detail(request, factcategory_name): + """Display info, and a random choice, for the fact category.""" + factcategory = get_object_or_404(FactCategory, name=factcategory_name) + + facts = [] + if factcategory.show_all_entries: + facts = [x.fact for x in factcategory.fact_set.all()] + + return render(request, 'facts/factcategory_detail.html', {'factcategory': factcategory, 'facts': facts}) diff --git a/static/css/facts.css b/static/css/facts.css new file mode 100644 index 0000000..0626d6a --- /dev/null +++ b/static/css/facts.css @@ -0,0 +1,4 @@ +.fact-category-items { + margin-top: 20px; + color: #999999; +} \ No newline at end of file diff --git a/templates/base.html b/templates/base.html index 366370f..1f2dd6f 100644 --- a/templates/base.html +++ b/templates/base.html @@ -73,6 +73,7 @@ {% block navbar_menu %}