From 0912fd15e8ef23a8d6a2212259b0b6935f520801 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomek=20W=C3=B3jcik?= Date: Sun, 7 Feb 2016 15:41:31 +0100 Subject: [PATCH] Initial public release of PieTime! \o/ --- .gitignore | 7 + CONTRIBUTING.md | 33 + LICENSE | 19 + MANIFEST.in | 4 + README.rst | 42 + docs/.gitignore | 1 + docs/Makefile | 177 +++++ docs/api.rst | 16 + docs/builtin_cards.rst | 22 + docs/conf.py | 261 ++++++ docs/developer_guide.rst | 104 +++ docs/index.rst | 69 ++ docs/requirements_and_installation.rst | 79 ++ docs/user_guide.rst | 295 +++++++ examples/__init__.py | 0 examples/basic_usage.py | 38 + examples/customization_example.py | 69 ++ examples/example.ini | 3 + extra/initscript.debian | 84 ++ extra/pie-time.ini.example | 7 + pie_time/__init__.py | 12 + pie_time/application.py | 511 ++++++++++++ pie_time/card.py | 195 +++++ pie_time/cards/__init__.py | 3 + pie_time/cards/clock.py | 154 ++++ pie_time/cards/picture.py | 140 ++++ pie_time/cards/resources/PTM55FT.ttf | Bin 0 -> 185912 bytes pie_time/cards/resources/linea-weather-10.ttf | Bin 0 -> 21308 bytes pie_time/cards/resources/opensans-light.ttf | Bin 0 -> 222412 bytes pie_time/cards/weather.py | 286 +++++++ pie_time/scripts/__init__.py | 0 pie_time/scripts/pie_time.py | 104 +++ requirements-dev.txt | 3 + requirements.txt | 2 + setup.py | 73 ++ tests/test_abstract_card.py | 89 +++ tests/test_application.py | 744 ++++++++++++++++++ tests/test_clock_card.py | 229 ++++++ tests/test_picture_card.py | 266 +++++++ tests/test_weather_card.py | 697 ++++++++++++++++ 40 files changed, 4838 insertions(+) create mode 100644 .gitignore create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE create mode 100644 MANIFEST.in create mode 100644 README.rst create mode 100644 docs/.gitignore create mode 100644 docs/Makefile create mode 100644 docs/api.rst create mode 100644 docs/builtin_cards.rst create mode 100644 docs/conf.py create mode 100644 docs/developer_guide.rst create mode 100644 docs/index.rst create mode 100644 docs/requirements_and_installation.rst create mode 100644 docs/user_guide.rst create mode 100644 examples/__init__.py create mode 100644 examples/basic_usage.py create mode 100644 examples/customization_example.py create mode 100644 examples/example.ini create mode 100644 extra/initscript.debian create mode 100644 extra/pie-time.ini.example create mode 100644 pie_time/__init__.py create mode 100644 pie_time/application.py create mode 100644 pie_time/card.py create mode 100644 pie_time/cards/__init__.py create mode 100644 pie_time/cards/clock.py create mode 100644 pie_time/cards/picture.py create mode 100755 pie_time/cards/resources/PTM55FT.ttf create mode 100644 pie_time/cards/resources/linea-weather-10.ttf create mode 100755 pie_time/cards/resources/opensans-light.ttf create mode 100644 pie_time/cards/weather.py create mode 100644 pie_time/scripts/__init__.py create mode 100644 pie_time/scripts/pie_time.py create mode 100644 requirements-dev.txt create mode 100644 requirements.txt create mode 100644 setup.py create mode 100644 tests/test_abstract_card.py create mode 100644 tests/test_application.py create mode 100644 tests/test_clock_card.py create mode 100644 tests/test_picture_card.py create mode 100644 tests/test_weather_card.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5d121c0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +*.pyc +*.pyo +*.swp +.pybuild/ +build/ +dist/ +pie_time.egg-info/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..0700c51 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,33 @@ +# Quick guide to contributing to PieTime + +This document describes the process of contributing to PieTime. + +## Mailing List + +The mailing list is the designated way of discussing anything related to +PieTime. Use it to report issues, submit patches etc. + +Mailing list address: pietime@librelist.com + +## Submitting patches + +If you've made changes to PieTime source, you're welcome to submit a patch. +Before doing so, make sure you've updated tests and docs to reflect your +changes. Additionally, run the *pep8* utility on changed files. + +Once you're done, create a patch from your changes and send it to the mailing +list along with a brief description. If your changes span over multiple +commits, please squash them into one before submitting the patch. + +## License information + +PieTime itself is licensed under the MIT license, so any code introduced by +your patch must be compatible with this license. Note that, if you don't +explicitly mark a piece of code with "alien" license, it'll automatically be +licensed under the MIT license. + +If your patch contains 3rd party resources, make sure that their license(s) +allow for redistribution in open source projects. + +If your patch contains 3rd party code and/or resources, make sure you update +the docs and ``debian/copyright`` file accordingly. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..cd505c8 --- /dev/null +++ b/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2014-2016 Tomek Wójcik + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..da92adb --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,4 @@ +include pie_time/cards/resources/*.ttf +include README.rst +include LICENSE +include requirements.txt diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..f99516a --- /dev/null +++ b/README.rst @@ -0,0 +1,42 @@ +PieTime +======= + +Desk clock for your Raspberry Pi. + +About +----- + +PieTime lets you turn your Raspberry Pi into a desk clock. It's written in +Python using PyGame framework. + +PieTime comes with three modules that allow displaying the clock, weather and +set of pictures. These modules (also known as *cards*) are highly configurable, +so you can tweak them to better suit your needs. + +Additionally, an API is provided for users who wish to write their own cards. +Read on for an example of a card. + +Features +-------- + +With PieTime you can: + +* Choose any of the three builtin cards. +* Configure display aspects (e.g. text color) of the cards. +* Define card visibility intervals. +* Set up screen blanking period for power saving. +* Use the card API to create your own cards. + +Author, License and Attributions +-------------------------------- + +PieTime has been created and is developed by +`Tomek Wójcik `_. + +PieTime is licensed under the MIT License. + +PieTime uses the following 3rd party code and resources: + +* Open Sans font by Steve Matteson, (Apache License, Version 2.0), +* Linea Weather 1.0 font by Dario Ferrando (CC BY 4.0), +* PT Mono font by Paratype (SIL OFL, Version 1.1). diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 0000000..69fa449 --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1 @@ +_build/ diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..9fa6ebc --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,177 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = _build + +# User-friendly check for sphinx-build +ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) +$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) +endif + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " xml to make Docutils-native XML files" + @echo " pseudoxml to make pseudoxml-XML files for display purposes" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + +clean: + rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/PiClock.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/PiClock.qhc" + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/PiClock" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/PiClock" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +latexpdfja: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through platex and dvipdfmx..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." + +xml: + $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml + @echo + @echo "Build finished. The XML files are in $(BUILDDIR)/xml." + +pseudoxml: + $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml + @echo + @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." diff --git a/docs/api.rst b/docs/api.rst new file mode 100644 index 0000000..300c683 --- /dev/null +++ b/docs/api.rst @@ -0,0 +1,16 @@ +API +=== + +This document describes the interfaces of PieTime. + +Application +----------- + +.. autoclass:: pie_time.PieTime + :members: + +Abstract Card +------------- + +.. autoclass:: pie_time.AbstractCard + :members: diff --git a/docs/builtin_cards.rst b/docs/builtin_cards.rst new file mode 100644 index 0000000..db1d43f --- /dev/null +++ b/docs/builtin_cards.rst @@ -0,0 +1,22 @@ +Builtin Cards +============= + +This document describes the builtin cards. + +ClockCard +--------- + +.. autoclass:: pie_time.cards.ClockCard + :members: + +PictureCard +----------- + +.. autoclass:: pie_time.cards.PictureCard + :members: + +WeatherCard +----------- + +.. autoclass:: pie_time.cards.WeatherCard + :members: diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 0000000..ce335ed --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,261 @@ +# -*- coding: utf-8 -*- +# +# PieTime documentation build configuration file, created by +# sphinx-quickstart on Tue Oct 21 16:34:31 2014. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys +import os + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +sys.path.insert(0, os.path.abspath('..')) + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.viewcode', +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'PieTime' +copyright = u'2014-2016, Tomek Wójcik' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '1.0' +# The full version, including alpha/beta/rc tags. +release = '1.0' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ['_build'] + +# The reST default role (used for this markup: `text`) to use for all +# documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + +# If true, keep warnings as "system message" paragraphs in the built documents. +#keep_warnings = False + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'nature' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Add any extra paths that contain custom files (such as robots.txt or +# .htaccess) here, relative to this directory. These files are copied +# directly to the root of the documentation. +#html_extra_path = [] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = 'PieTimedoc' + + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +#'papersize': 'letterpaper', + +# The font size ('10pt', '11pt' or '12pt'). +#'pointsize': '10pt', + +# Additional stuff for the LaTeX preamble. +#'preamble': '', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + ('index', 'PieTime.tex', u'PieTime Documentation', + u'Tomek Wójcik', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ('index', 'pie_time', u'PieTime Documentation', + [u'Tomek Wójcik'], 1) +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + ('index', 'PieTime', u'PieTime Documentation', + u'Tomek Wójcik', 'PieTime', 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' + +# If true, do not generate a @detailmenu in the "Top" node's menu. +#texinfo_no_detailmenu = False diff --git a/docs/developer_guide.rst b/docs/developer_guide.rst new file mode 100644 index 0000000..cf1326a --- /dev/null +++ b/docs/developer_guide.rst @@ -0,0 +1,104 @@ +Developer Guide +=============== + +This document provides guide to hacking and extending PieTime. + +Setup +----- + +To develop PieTime or cards, some additional setup is required. First, it's +recommended to use a virtual environment, to separate from OS Python and +extensions. Secondly, use ``requirements-dev.txt`` to install additional +modules and tools used in development. + +Custom card example +------------------- + +.. sourcecode:: python + + from pie_time.card import AbstractCard + + import pygame + + class ExampleCard(AbstractCard): + def initialize(self): + self.sprite = pygame.surface.Surface((20, 20)) + self.sprite.fill((255, 0, 0)) + self.orig_sprite_rect = self.sprite.get_rect() + self.orig_speed = [2, 2] + self.sprite_rect = self.orig_sprite_rect + self.speed = self.orig_speed + + def show(self): + self.sprite_rect = self.orig_sprite_rect + self.speed = self.orig_speed + + def tick(self): + self.sprite_rect = self.sprite_rect.move(self.speed) + + if self.sprite_rect.left < 0 or self.sprite_rect.right > self.width: + self.speed[0] = -self.speed[0] + if self.sprite_rect.top < 0 or self.sprite_rect.bottom > self.height: + self.speed[1] = -self.speed[1] + + self.surface.fill(self.background_color) + self.surface.blit(self.sprite, self.sprite_rect) + +This example shows how easy it is to create custom cards for use in PieTime +decks. + +Start by creating a custom class that inherits from *AbstractCard*. Then +implement a few methods to make it display the information you need (in this +example, a red square moving on the screen). Having done that, you'll be ready to use your custom card in a deck. + +Head on to :py:class:`pie_time.AbstractCard` documentation for more +information about PieTime card API. + +Speed considerations +-------------------- + +Since PieTime targets the Raspberry Pi, it's important to keep speed in mind. +When developing cards, take care to do as little work as possible in the +:py:meth:`pie_time.AbstractCard.tick` method. + +For example, WeatherCard redraws its surface only when weather conditions +change. By doing so, the CPU load is reduced because the only thing PieTime has to do is blit the surface to screen. + +Always test the behavior of your card in low FPS. Remember, that PieTime +targets small GPIO-connected LCD screens. For many of them, 20 FPS will be the best refresh rate. If your card behaves badly in such conditions, users may refrain from using it. + +Threading considerations +------------------------ + +Sometimes, it's required to perform background tasks during lifetime of the +card. API exposed by Python's builtin ``threading`` module should come in handy +is such situations. + +Take WeatherCard as an example. Once every 10 minutes, it fetches current +conditions from the Internet. If you look into the card's code, there's +``_refresh_conditions`` method. It uses ``threading.Timer`` class to schedule +fetching of the conditions in a separate thread of control. This way, the +HTTP request (which may take some time depending on the network conditions) +won't cause the PieTime application to freeze. + +As always with threads, you should be aware of the standard pitfalls - variable +access synchronization, error handling, the GIL. Also, spawning too many +threads will impact PieTime's performance. If you use threads in your card, +make sure to test it on the device to see how it impacts the load. + +Handling events +--------------- + +In every iteration of the main loop, PieTime reads list of current events from +PyGame. This list is available for the cards to use through +:py:attr:`pie_time.PieTime.events`. + +The application itself handles the following events: + +* ``QUIT`` (e.g. SIGTERM) - if this event appears, the application quits. +* ``KEYDOWN`` on the key specified by :py:attr:`pie_time.PieTime.KEY_QUIT` - + quits the application, +* ``MOUSEBUTTONDOWN`` anywhere on the screen when it's blanked - + if click to unblank is enabled, +* ``MOUSEBUTTONDOWN`` in one of the regions used to manually switch bedween + cards. diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 0000000..e15e411 --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,69 @@ +PieTime +======= + +Desk clock for your Raspberry Pi. + +About +----- + +PieTime lets you turn your Raspberry Pi into a desk clock. It's written in +Python using Pygame framework. + +PieTime comes with three modules that allow displaying the clock, weather and +set of pictures. These modules (also known as *cards*) are highly configurable, +so you can tweak them to better suit your needs. + +Additionally, an API is provided for users who wish to write their own cards. +Read on for an example of a card. + +Features +-------- + +With PieTime you can: + +* Choose any of the three builtin cards. +* Configure display aspects (e.g. text color) of the cards. +* Define card visibility intervals. +* Set up screen blanking period for power saving. +* Use the card API to create your own cards. + +Author, License and Attributions +-------------------------------- + +PieTime has been created and is developed by +`Tomek Wójcik `_. + +PieTime is licensed under the MIT License. + +PieTime uses the following 3rd party code and resources: + +* Open Sans font by Steve Matteson, (Apache License, Version 2.0), +* Linea Weather 1.0 font by Dario Ferrando (CC BY 4.0), +* PT Mono font by Paratype (SIL OFL, Version 1.1). + +Source code and issues +---------------------- + +Source code is available via +`public Git repository `_. + +If you wish to contribute to the project, see ``CONTRIBUTING.md`` for more +info. + +Contents +-------- + +.. toctree:: + :maxdepth: 2 + + requirements_and_installation + user_guide + builtin_cards + developer_guide + api + +Indices and tables +------------------ + +* :ref:`genindex` +* :ref:`search` diff --git a/docs/requirements_and_installation.rst b/docs/requirements_and_installation.rst new file mode 100644 index 0000000..b9f00a2 --- /dev/null +++ b/docs/requirements_and_installation.rst @@ -0,0 +1,79 @@ +.. _requirements_and_installation: + +Requirements and installation +============================= + +This document describes the PieTime requirements and installation process. + +Requirements +------------ + +PieTime requires the following to work: + +* Python 2.7, +* PyGame 1.9.1 (also tested with 1.9.2a0), +* requests 2.4.1 (should work with newer versions). + +Installing on Raspbian Jessie +----------------------------- + +If you're using Raspbian Jessie on your Raspberry Pi, you can install PieTime +using binary packages by following the guide below. + +**Add PieTime APT repository** + +Create the file /etc/apt/sources.list.d/pie-time.list and add the following +line: + +.. sourcecode:: text + + deb https://pie-time.bthlabs.pl/repos/apt/ raspbian-jessie main + +**Import the repository signing key** + +.. sourcecode:: console + + $ wget --quiet -O - https://pie-time.bthlabs.pl/keys/apt.asc | sudo apt-key add - + +**Update the package lists and install PieTime** + +.. sourcecode:: console + + $ sudo apt-get update + $ sudo apt-get install pie-time + +Installing on other systems using PyPI +-------------------------------------- + +If you wish to install PieTime on system other than Raspbian Jessie (and +potentially on device other than Raspberry Pi), you can do so using the +PyPI package by using the guide below. + +#. Install PyGame dependencies, +#. Run ``$ sudo pip install pie_time`` to install PieTime and its dependencies. + +**NOTE**: The second step may require installing additional packages from the +system repository, depending on your current setup. + +Installing from the source +-------------------------- + +In order to install PieTime, please follow the guide below. Note that this +guide assumes Unix-like OS and root access. + +#. Install PyGame dependencies, +#. Clone the repository ``$ git clone https://git.bthlabs.pl/tomekwojcik/pie-time.git``, +#. Enter the PieTime directory: ``$ cd pie-time``, +#. Install PieTime: ``$ python setup.py install``. + +**NOTE**: The fourth step may require installing additional packages from the +system repository, depending on your current setup. + +Installing as non-root user +--------------------------- + +If you wish to install PieTime as non-root user, you can do so by installing +it from the PyPI package or source code using a virtual env. + +To learn more about Python virtual envs, see the +`virtual env documentation `_ diff --git a/docs/user_guide.rst b/docs/user_guide.rst new file mode 100644 index 0000000..898ebcb --- /dev/null +++ b/docs/user_guide.rst @@ -0,0 +1,295 @@ +.. _user_guide: + +User Guide +========== + +This document provides guide to using PieTime. + +The application script +---------------------- + +In order to use PieTime, you'll have to write a simple Python script to set +up and (optionally) start the application. + +**Short example** + +.. sourcecode:: python + + #!/usr/bin/env python2.7 + + from datetime import timedelta + import os + import sys + + if os.getcwd() not in sys.path: + sys.path.insert(0, os.getcwd()) + + from pie_time import PieTime + from pie_time.cards import ClockCard, PictureCard, WeatherCard + + deck = [ + ClockCard, + ( + WeatherCard, 20, { + 'api_key': 'Your OpenWeatherMap API KEY', + 'city': 'Wroclaw,PL' + } + ), + ( + PictureCard, 10, { + 'urls': [ + 'http://lorempixel.com/320/240/city', + 'http://lorempixel.com/200/125/technics' + ] + } + ) + ] + + blanker_schedule = ( + timedelta(hours=23), timedelta(hours=6) + ) + + app = PieTime(deck, blanker_schedule=blanker_schedule) + + if __name__ == '__main__': + app.run() + +This script sets up PieTime application with the following settings: + +* Three cards, +* Clock card set up to display for 60 seconds, +* Weather card set up to fetch data for the city of Wrocław in Poland and + display for 20 seconds, +* Picture frame card set to display two separate images (fetched from the Net) + for 10 seconds each. +* Blanker schedule set up to blank the screen between 23:00 (11:00 PM) and + 6:00 AM, +* Click to unblank interval set to 10 seconds. + +The deck +-------- + +The first argument passed to :py:class:`pie_time.PieTime` constructor defines +the deck of cards to be displayed, along with additional information about +each of the cards. + +Example deck could look like this: + +.. sourcecode:: python + + deck = [ + ClockCard, + (ClockCard, 30), + (ClockCard, 30, {'text_color': (255, 0, 0)}), + ] + +The first item is just a card class. A card defined this way will display +for the duration defined by :py:attr:`pie_time.PieTime.CARD_INTERVAL` and +won't have any additional settings. + +The second item is a tuple of card class and number. A card defined this +way will display for the specified number of seconds and won't have any +additional settings. + +The third item is a tuple of card class, number and dictionary. A card +defined this way will display for the specified number of seconds and will +have additional settings as specified by the dictionary. + +Blanker schedule +---------------- + +The *blanker_schedule* keyword argument defines how the screen should be +blanked. + +Example blanker schedule could look like this: + +.. sourcecode:: python + + blanker_schedule = ( + datetime.timedelta(hours=23), datetime.timedelta(hours=6) + ) + +Such a schedule will make the application blank the screen between 23:00 +(11:00 PM) and 6:00 AM. + +When the blanker is active, the screen is filled with color defined in +:py:attr:`pie_time.PieTime.BLANK_COLOR`. + +Blanker also prevents the following actions: + +* Transitioning cards, +* Calling the visible card's ``tick()`` method, +* Blitting the visible card's surface to the screen. + +When the blanker deactivates it transitions to the first card from the deck. + +Click to unblank +---------------- + +A PieTime application can be set up to allow temporary overriding of the screen +blanker. In order to do so, set *click_to_unblank_interval* to a non-negative +number. When the screen is blanked, just click anywhere and PieTime will show +for number of seconds defined by *click_to_unblank_interval*. Before +unblanking, PieTime will set the first card from deck as the current card. + +Since PieTime uses PyGame, it'll automatically support many input devices. For +example, a properly configured touch screen for PiTFT-like displays should be +supported out of the box. + +Click to transition +------------------- + +If you wish, you can change the currently visible card manually. In order to do +so, just click (or tap) the bottom-left or bottom-right corner of the screen. +The bottom-left corner will switch to the previous card. The bottom-right +corner will switch to the next card. + +This feature is enabled automatically and can be disabled by setting +*click_to_transition* keyword argument to ``False``. + +Other settings +-------------- + +PieTime app allows changing other settings. Have a look at +:py:class:`pie_time.PieTime` class documentation to learn more. + +Video drivers and screen size +----------------------------- + +Since PieTime is based on PyGame, it supports the same range ouf output +devices. As of time of writing this document, PieTime has been tested with +``x11``, ``fbcon`` and ``Quartz`` video drivers. + +You can configure the outut device using SDL environment variables. See the +`SDL environment variables documentation `_ to learn more. + +Since PieTime mostly targets LCD shields, the screen size defaults to +320x240px. Support for other screen sizes is limited. + +Testing the script +------------------ + +Once you've created the script to set up the application and chosen the video +driver, you can start PieTime manually using the following command: + +.. sourcecode:: console + + $ python2.7 + +In this case, video driver will be chosen automatically. If you get any +errors, try using a different video driver. Note that framebuffer drivers +usually require root privileges. + +To exit the application, press *[ESC]*. + +**NOTE**: If you installed PieTime from the PyPI package or source code in a +virtual env, make sure it's properly activated before trying to start the +application. + +Creating and using the PieTime INI file +--------------------------------------- + +After you've tested your application script and are satisfied with it, it's +time to create the INI file. This INI file will be used by the *pie_time* +program to set up and launch your application. + +**Short example** + +.. sourcecode:: ini + + [PieTime] + app_module = examples.customization_example:app + log_path = log.txt + + [SDL] + VIDEODRIVER = fbcon + +**The PieTime section** + +The *PieTime* section should contain the following fields: + +* ``app_module`` (string) - app module import path, +* ``log_path`` (string) - optional path to log file (if omitted, standard + output will be used). + +**The app module import path** + +The *app_module* field defines the app module import path. This import path +will be used to import app script and extract the app object from it. In the +example, the import path translates to *app attribute in customization_example +module in examples package*. Note that the import path is related to the +current working directory. + +**The SDL section** + +The SDL section allows you to set up SDL environment variables before starting +the PieTime application. You can specify any environment variable supported by +SDL. The field names should be specified without the ``SDL_`` prefix, which +will be added automatically. + +Starting PieTime on boot +------------------------ + +Since PieTime was designed as a desk clock replacement, it's best to have it +start automatically on boot. In order to do so, please follow instructions in +one of the subsections. + +**Setting up PieTime installed from APT repository** + +If you installed PieTime from APT repository, follow the guide below to set it +up to start on boot. + +#. Edit ``/etc/default/pie-time`` and adjust its contents according to your + needs, +#. Place the INI file in the path specified in the ``/etc/default/pie-time`` + file, +#. Place your application script in the path specified in the INI file, +#. Run ``$ sudo dpkg-reconfigure pie-time`` and answer *Yes* when it asks you + about starting on boot, +#. Either reboot the Raspberry Pi or run + ``$ sudo /etc/init.d/pie-time restart`` to start PieTime. + +**NOTE**: You can skip the third step, if you replied *Yes* to the question +when installing the PieTime package. + +**The /etc/default/pie-time file** + +The ``/etc/default/pie-time`` file contains minimum shell environment required +to properly start the *pie_time* program. + +Supported environment variables: + +* ``WORKDIR`` - path to working directory (which will be used to import the app + module). Defaults to ``/var/lib/pie-time``. +* ``INI_PATH`` - path to the INI file. Defaults to ``/etc/pie-time.ini``. +* ``USER`` - name of the user which will start the app. Defaults to ``root``. + +**NOTE**: If you change the ``USER`` field to a non-root user, make sure it can +acess the selected output device and paths (most notably, the log path). + +**Setting up PieTime installed from PyPI package or source code** + +If you chose to install PieTime from PyPI package or source code and wish to +start it on boot, the recommended method is to use +`supervisor `_ to achieve that. + +**Example supervisor config for PieTime** + +.. sourcecode:: text + + [program:pie_time] + command=/usr/bin/python2.7 /home/pi/pie-time/app.py + numprocs=1 + directory=/home/pi/pie-time + autostart=true + user=root + stdout_logfile=/home/pi/pie-time/log/stdout.log + stderr_logfile=/home/pi/pie-time/log/stderr.log + +Troubleshooting +--------------- + +In case of any problems, it's recommend to set the *verbose* keyword to +argument to ``True`` and start the app again. In verbose mode, the app's logger +is set to ``DEBUG`` level (as opposed to ``INFO`` in non-verbose mode) and will +display a lot of useful debugging information. diff --git a/examples/__init__.py b/examples/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/examples/basic_usage.py b/examples/basic_usage.py new file mode 100644 index 0000000..b8a8492 --- /dev/null +++ b/examples/basic_usage.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python2.7 + +from datetime import timedelta +import os +import sys + +if os.getcwd() not in sys.path: + sys.path.insert(0, os.getcwd()) + +from pie_time import PieTime +from pie_time.cards import ClockCard, PictureCard, WeatherCard + +deck = [ + ClockCard, + ( + WeatherCard, 20, { + 'api_key': 'Your OpenWeatherMap API KEY', + 'city': 'Wroclaw,PL' + } + ), + ( + PictureCard, 10, { + 'urls': [ + 'http://lorempixel.com/320/240/city', + 'http://lorempixel.com/200/125/technics' + ] + } + ) +] + +blanker_schedule = ( + timedelta(hours=23), timedelta(hours=6) +) + +app = PieTime(deck, blanker_schedule=blanker_schedule) + +if __name__ == '__main__': + app.run() diff --git a/examples/customization_example.py b/examples/customization_example.py new file mode 100644 index 0000000..ae676c6 --- /dev/null +++ b/examples/customization_example.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- + +from datetime import datetime, timedelta +import os +import sys +import time + +if os.getcwd() not in sys.path: + sys.path.insert(0, os.getcwd()) + +from pie_time import PieTime +from pie_time.cards import ClockCard +from pie_time.card import AbstractCard + +import pygame + + +class ExampleCard(AbstractCard): + def initialize(self): + self.sprite = pygame.surface.Surface((20, 20)) + self.sprite.fill((255, 0, 0)) + self.orig_sprite_rect = self.sprite.get_rect() + self.orig_speed = [2, 2] + self.sprite_rect = self.orig_sprite_rect + self.speed = self.orig_speed + + def show(self): + self.sprite_rect = self.orig_sprite_rect + self.speed = self.orig_speed + + def tick(self): + self.sprite_rect = self.sprite_rect.move(self.speed) + + if self.sprite_rect.left < 0 or self.sprite_rect.right > self.width: + self.speed[0] = -self.speed[0] + if self.sprite_rect.top < 0 or self.sprite_rect.bottom > self.height: + self.speed[1] = -self.speed[1] + + self.surface.fill(self.background_color) + self.surface.blit(self.sprite, self.sprite_rect) + + +class CustomApp(PieTime): + def __init__(self, *args, **kwargs): + super(CustomApp, self).__init__(*args, **kwargs) + self._ctt_region_prev = pygame.Rect(0, 0, 160, 240) + self._ctt_region_next = pygame.Rect(160, 0, 160, 240) + + def will_blank(self): + self.logger.debug('CustomApp.will_blank') + + def will_unblank(self): + self.logger.debug('CustomApp.will_unblank') + +deck = [ + (ClockCard, 10), + (ExampleCard, 10), +] + +app = CustomApp( + deck, verbose=True, fps=40, + blanker_schedule=( + timedelta(hours=23), timedelta(hours=6) + ), + click_to_unblank_interval=10 +) + +if __name__ == '__main__': + app.run() diff --git a/examples/example.ini b/examples/example.ini new file mode 100644 index 0000000..695172c --- /dev/null +++ b/examples/example.ini @@ -0,0 +1,3 @@ +[PieTime] +app_module = examples.customization_example:app +log_path = log.txt diff --git a/extra/initscript.debian b/extra/initscript.debian new file mode 100644 index 0000000..dfe7159 --- /dev/null +++ b/extra/initscript.debian @@ -0,0 +1,84 @@ +#!/bin/bash +### BEGIN INIT INFO +# Provides: pie-time +# Required-Start: $network +# Required-Stop: $network +# Should-Start: $local_fs +# Should-Stop: $local_fs +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Desk clock application for the Raspberry Pi +# Description: Desk clock application for the Raspberry Pi +### END INIT INFO + +PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin +DAEMON="/usr/bin/pie_time" +NAME="pie-time" +DESC="Desk clock application for the Raspberry Pi" + +RUNDIR="/var/run/pie-time" +PIDFILE="/var/run/pie-time/pie-time.pid" +WORKDIR="/var/lib/pie-time" + +CONFIG_PATH="/etc/pie-time.ini" +USER="root" + +if [ -f "/etc/default/pie-time" ];then + . "/etc/default/pie-time" +fi + +. /lib/lsb/init-functions + +set -e + +case "$1" in + start) + echo -n "Starting $DESC: " + mkdir -p $RUNDIR + chmod 755 $RUNDIR + + chown $USER $RUNDIR + + if start-stop-daemon --start --quiet --pidfile $PIDFILE --chuid $USER --chdir $WORKDIR -b -m --exec $DAEMON -- $CONFIG_PATH;then + echo "$NAME." + else + echo "failed" + fi + ;; + stop) + echo -n "Stopping $DESC: " + if start-stop-daemon --stop --retry forever/TERM/1 --quiet --oknodo --pidfile $PIDFILE;then + echo "$NAME." + rm -f $PIDFILE + else + echo "failed" + fi + ;; + restart|force-reload) + ${0} stop + ${0} start + ;; + status) + STATUS="4" + start-stop-daemon --status --pidfile $PIDFILE || STATUS="$?" + case $STATUS in + 0) + echo "$NAME: running" + ;; + + 1|3) + echo "$NAME: not running" + ;; + + *) + echo "$NAME: unable to determine the status" + ;; + esac + ;; + *) + echo "Usage: /etc/init.d/$NAME {start|stop|restart|force-reload|status}" >&2 + exit 1 + ;; +esac + +exit 0 diff --git a/extra/pie-time.ini.example b/extra/pie-time.ini.example new file mode 100644 index 0000000..427a697 --- /dev/null +++ b/extra/pie-time.ini.example @@ -0,0 +1,7 @@ +[PieTime] +app_module = pie_time_app:app +log_path = /var/log/pie-time/daemon.log + +[SDL] +VIDEODRIVER = fbcon +FBDEV = /dev/fb0 diff --git a/pie_time/__init__.py b/pie_time/__init__.py new file mode 100644 index 0000000..a8f61d7 --- /dev/null +++ b/pie_time/__init__.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- + +__title__ = 'pie_time' +__version__ = '1.0' +__author__ = u'Tomek Wójcik' +__license__ = 'MIT' +__copyright__ = ( + u'Copyright (c) 2014-2016 Tomek Wójcik ' +) + +from .application import PieTime +from .card import AbstractCard diff --git a/pie_time/application.py b/pie_time/application.py new file mode 100644 index 0000000..8246a0d --- /dev/null +++ b/pie_time/application.py @@ -0,0 +1,511 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2014-2016 Tomek Wójcik +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# + +""" +pie_time.application +==================== + +This module implements the PieTime application. +""" + +import datetime +import argparse +import imp +import logging +import os +import sys + +import pygame + +from pie_time import __copyright__ as copyright, __version__ as version + +RET_OK = 0 +RET_ERROR = 99 + +MOTD_PICLOCK_BANNER = u"PieTime v%s by Tomek Wójcik" % ( + version +) +MOTD_LICENSE_BANNER = u"Released under the MIT license" + +EVENT_QUIT = 0 +EVENT_CLICK_TO_UNBLANK = 1 +EVENT_CLICK_TO_PREV_CARD = 2 +EVENT_CLICK_TO_NEXT_CARD = 3 + + +class Quit(Exception): + pass + + +class PieTimeEvent(object): + def __init__(self, app, event): + self.event = event + self.app = app + + def is_quit(self): + return (self.event.type == pygame.QUIT) + + def is_key_quit(self): + return ( + self.event.type == pygame.KEYDOWN + and self.event.key == self.app.KEY_QUIT + ) + + def is_click_to_unblank(self): + return ( + self.event.type == pygame.MOUSEBUTTONDOWN + and self.app._click_to_unblank_interval is not None + and self.app._is_blanked is True + ) + + def is_click_to_prev_card(self): + return ( + self.event.type == pygame.MOUSEBUTTONDOWN + and self.app._click_to_transition is True + and self.app._is_blanked is False + and self.app._ctt_region_prev.collidepoint(self.event.pos) == 1 + ) + + def is_click_to_next_card(self): + return ( + self.event.type == pygame.MOUSEBUTTONDOWN + and self.app._click_to_transition is True + and self.app._is_blanked is False + and self.app._ctt_region_next.collidepoint(self.event.pos) == 1 + ) + + +class PieTime(object): + """ + The PieTime application. + + :param deck: the deck + :param screen_size: tuple of (width, height) to use as the screen size + :param fps: number of frames per second to limit rendering to + :param blanker_schedule: blanker schedule + :param click_to_unblank_interval: time interval for click to unblank + :param click_to_transition: boolean defining if click to transition is + enabled + :param verbose: boolean defining if verbose logging should be on + :param log_path: path to log file (if omitted, *stdout* will be used) + """ + + #: Default background color + BACKGROUND_COLOR = (0, 0, 0) + + #: Blanked screen color + BLANK_COLOR = (0, 0, 0) + + #: Default card display duration interval + CARD_INTERVAL = 60 + + #: Defines key which quits the application + KEY_QUIT = pygame.K_ESCAPE + + #: Defines size of click to transition region square + CLICK_TO_TRANSITION_REGION_SIZE = 30 + + _DEFAULT_OUTPUT_STREAM = sys.stdout + + _STREAM_FACTORY = file + + def __init__(self, deck, screen_size=(320, 240), fps=20, + blanker_schedule=None, click_to_unblank_interval=None, + click_to_transition=True, verbose=False, log_path=None): + self._deck = deck + + #: The screen surface + self.screen = None + #: The screen size tuple + self.screen_size = screen_size + #: List of events captured in this frame + self.events = [] + #: Path to log file. If `None`, *stdout* will be used for logging. + self.log_path = log_path + + self._fps = fps + self._verbose = verbose + self._blanker_schedule = blanker_schedule + self._click_to_unblank_interval = click_to_unblank_interval + self._click_to_transition = click_to_transition + self._clock = None + self._cards = [] + self._is_blanked = False + self._current_card_idx = None + self._current_card_time = None + self._should_quit = False + self._internal_events = set() + self._ctu_timer = None + self._output_stream = None + + self._ctt_region_prev = pygame.Rect( + 0, + self.screen_size[1] - self.CLICK_TO_TRANSITION_REGION_SIZE, + self.CLICK_TO_TRANSITION_REGION_SIZE, + self.CLICK_TO_TRANSITION_REGION_SIZE + ) + + self._ctt_region_next = pygame.Rect( + self.screen_size[0] - self.CLICK_TO_TRANSITION_REGION_SIZE, + self.screen_size[1] - self.CLICK_TO_TRANSITION_REGION_SIZE, + self.CLICK_TO_TRANSITION_REGION_SIZE, + self.CLICK_TO_TRANSITION_REGION_SIZE + ) + + def _should_blank(self, now=None): + if self._has_click_to_unblank_event() or self._ctu_timer is not None: + if self._is_blanked is False and self._ctu_timer is None: + self._ctu_timer = None + return False + + if self._click_to_unblank_interval is not None: + if self._ctu_timer is None: + self._ctu_timer = self._click_to_unblank_interval + return False + + self._ctu_timer -= self._clock.get_time() / 1000.0 + if self._ctu_timer <= 0: + self._ctu_timer = None + return True + else: + return False + + if self._blanker_schedule: + delta_blanker_start, delta_blanker_end = self._blanker_schedule + + if now is None: + now = datetime.datetime.now() + + midnight = now.replace(hour=0, minute=0, second=0, microsecond=0) + + blanker_start = midnight + delta_blanker_start + blanker_end = midnight + delta_blanker_end + + if blanker_start > blanker_end: + if now.hour < 12: + blanker_start -= datetime.timedelta(days=1) + else: + blanker_end += datetime.timedelta(days=1) + + if now >= blanker_start and now < blanker_end: + return True + + return False + + def _blank(self): + if self._is_blanked is False: + self.logger.debug('Blanking the screen!') + self.will_blank() + + self._is_blanked = True + self.screen.fill(self.BLANK_COLOR) + + def _unblank(self): + if self._is_blanked: + self.logger.debug('Unblanking the screen!') + self.will_unblank() + + self._is_blanked = False + self._current_card_idx = 0 + self._current_card_time = 0 + + self._cards[self._current_card_idx][0].show() + + def _transition_cards(self, direction=1, force=False): + if self._current_card_idx is None and force is False: + self._current_card_idx = 0 + self._current_card_time = 0 + self._cards[self._current_card_idx][0].show() + elif len(self._cards) > 1: + self._current_card_time += self._clock.get_time() / 1000.0 + card_interval = self._cards[self._current_card_idx][1] + if self._current_card_time >= card_interval or force is True: + new_card_idx = self._current_card_idx + direction + if new_card_idx >= len(self._cards): + new_card_idx = 0 + elif new_card_idx < 0: + new_card_idx = len(self._cards) - 1 + + self.logger.debug('Card transition: %d -> %d' % ( + self._current_card_idx, new_card_idx + )) + + self._cards[self._current_card_idx][0].hide() + + self._current_card_idx = new_card_idx + self._current_card_time = 0 + + self._cards[self._current_card_idx][0].show() + + def _get_events(self): + self._internal_events = set() + self.events = [] + for event in pygame.event.get(): + pie_time_event = PieTimeEvent(self, event) + if pie_time_event.is_quit(): + self.logger.debug('_get_events: QUIT') + self._internal_events.add(EVENT_QUIT) + elif pie_time_event.is_key_quit(): + self.logger.debug('_get_events: KEY_QUIT') + self._internal_events.add(EVENT_QUIT) + elif pie_time_event.is_click_to_unblank(): + self.logger.debug('_get_events: CLICK_TO_UNBLANK') + self._internal_events.add(EVENT_CLICK_TO_UNBLANK) + elif pie_time_event.is_click_to_prev_card(): + self.logger.debug('_get_events: CLICK_TO_PREV_CARD') + self._internal_events.add(EVENT_CLICK_TO_PREV_CARD) + elif pie_time_event.is_click_to_next_card(): + self.logger.debug('_get_events: CLICK_TO_NEXT_CARD') + self._internal_events.add(EVENT_CLICK_TO_NEXT_CARD) + else: + self.events.append(event) + + def _has_quit_event(self): + return (EVENT_QUIT in self._internal_events) + + def _has_click_to_unblank_event(self): + return (EVENT_CLICK_TO_UNBLANK in self._internal_events) + + def _start_clock(self): + self._clock = pygame.time.Clock() + + def _setup_output_stream(self): + if self.log_path is None: + self._output_stream = self._DEFAULT_OUTPUT_STREAM + else: + self._output_stream = self._STREAM_FACTORY(self.log_path, 'a') + + def _setup_logging(self): + logger = logging.getLogger('PieTime') + requests_logger = logging.getLogger('requests') + + if self._verbose: + logger.setLevel(logging.DEBUG) + else: + logger.setLevel(logging.INFO) + requests_logger.setLevel(logging.WARNING) + + handler = logging.StreamHandler(self._output_stream) + formatter = logging.Formatter( + '%(asctime)s PieTime: %(levelname)s: %(message)s' + ) + handler.setFormatter(formatter) + logger.addHandler(handler) + + for requests_handler in requests_logger.handlers: + requests_logger.removeHandler(requests_handler) + + requests_logger.addHandler(handler) + + @property + def logger(self): + """The application-wide :py:class:`logging.Logger` object.""" + if not hasattr(self, '_logger'): + self._logger = logging.getLogger('PieTime') + + return self._logger + + def init_pygame(self): + """Initializes PyGame and the internal clock.""" + self.logger.debug('Initializing PyGame.') + pygame.init() + pygame.mouse.set_visible(False) + + def quit_pygame(self): + """Quits PyGame.""" + self.logger.debug('Quitting PyGame.') + pygame.quit() + + self._clock = None + + def init_cards(self): + """ + Initializes the cards. + + Initialization of a card consits of the following steps: + + * Creating an instance of the card class, + * Binding the card with the application + (:py:meth:`pie_time.AbstractCard.set_app`), + * Setting the card's settings + (:py:meth:`pie_time.AbstractCard.set_settings`), + * Initializing the card (:py:meth:`pie_time.AbstractCard.initialize`). + """ + self.logger.debug('Initializing cards.') + for i in xrange(0, len(self._deck)): + card_def = self._deck[i] + + klass = None + interval = self.CARD_INTERVAL + settings = {} + + if not isinstance(card_def, tuple): + klass = card_def + elif len(card_def) == 2: + klass, interval = card_def + elif len(card_def) == 3: + klass, interval, settings = card_def + + if klass is not None: + card = klass() + card.set_app(self) + card.set_settings(settings) + card.initialize() + + self._cards.append((card, interval)) + else: + self.logger.warning('Invalid deck entry at index: %d' % i) + + def destroy_cards(self): + """ + Destroys the cards. + + Calls the :py:meth:`pie_time.AbstractCard.quit` of each card. + """ + self.logger.debug('Destroying cards.') + while len(self._cards) > 0: + card, _ = self._cards.pop() + + try: + card.quit() + except: + self.logger.error('ERROR!', exc_info=True) + + def get_screen(self): + """Creates and returns the screen screen surface.""" + self.logger.debug('Creating screen.') + return pygame.display.set_mode(self.screen_size) + + def fill_screen(self): + """ + Fills the screen surface with color defined in + :py:attr:`pie_time.PieTime.BACKGROUND_COLOR`. + """ + self.screen.fill(self.BACKGROUND_COLOR) + + def run(self, standalone=True): + """ + Runs the application. + + This method contains the app's main loop and it never returns. Upon + quitting, this method will call the :py:func:`sys.exit` function with + the status code (``99`` if an unhandled exception occurred, ``0`` + otherwise). + + The application will quit under one of the following conditions: + + * An unhandled exception reached this method, + * PyGame requested to quit (e.g. due to closing the window), + * Some other code called the :py:meth:`pie_time.PieTime.quit` method on + the application. + + Before quitting the :py:meth:`pie_time.PieTime.destroy_cards` and + :py:meth:`pie_time.PieTime.quit_pygame` methods will be called to clean + up. + """ + result = RET_OK + + self._setup_output_stream() + self._setup_logging() + + try: + self.logger.info(MOTD_PICLOCK_BANNER) + self.logger.info(copyright) + self.logger.info(MOTD_LICENSE_BANNER) + self.logger.debug('My PID = %d' % os.getpid()) + + self.init_pygame() + self.screen = self.get_screen() + + self.init_cards() + + self._start_clock() + + while True: + self._get_events() + + if self._should_quit or self._has_quit_event(): + raise Quit() + + if not self._should_blank(): + self._unblank() + + if EVENT_CLICK_TO_PREV_CARD in self._internal_events: + self._transition_cards(direction=-1, force=True) + elif EVENT_CLICK_TO_NEXT_CARD in self._internal_events: + self._transition_cards(direction=1, force=True) + else: + self._transition_cards() + + card = self._cards[self._current_card_idx][0] + + card.tick() + + self.fill_screen() + self.screen.blit( + card.surface, (0, 0, card.width, card.height) + ) + else: + self._blank() + + pygame.display.flip() + + self._clock.tick(self._fps) + except Exception as exc: + if not isinstance(exc, Quit): + self.logger.error('ERROR!', exc_info=True) + result = RET_ERROR + finally: + self.destroy_cards() + self.quit_pygame() + + if standalone: + sys.exit(result) + else: + return result + + def quit(self): + """Tells the application to quit.""" + self._should_quit = True + + def will_blank(self): + """ + Called before blanking the screen. + + This method can be used to perform additional operations before + blanking the screen. + + The default implementation does nothing. + """ + pass + + def will_unblank(self): + """ + Called before unblanking the screen. + + This method can be used to perform additional operations before + unblanking the screen. + + The default implementation does nothing. + """ + + pass diff --git a/pie_time/card.py b/pie_time/card.py new file mode 100644 index 0000000..bd4cfe6 --- /dev/null +++ b/pie_time/card.py @@ -0,0 +1,195 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2014-2016 Tomek Wójcik +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# + +""" +pie_time.card +============= + +This module contains the AbstractCard class. +""" + +import os +import sys + +import pygame + + +class AbstractCard(object): + """ + The abstract card class. + + All the custom cards **must** inherit from this class. + + **Application binding and settings.** + + The application calls the card's :py:meth:`pie_time.AbstractCard.set_app` + and :py:meth:`pie_time.AbstractCard.set_settings` methods during + initialization (before calling the + :py:meth:`pie_time.AbstractCard.initialize` method). + + The application reference is stored in ``_app`` attribute. + + The settings dictionary is stored in ``_settings`` attribute and defaults + to an empty dictionary. + + **Drawing** + + All the drawing on the card's surface should be done in the + :py:meth:`pie_time.AbstractCard.tick` method. The method's implementation + should be as fast as possible to avoid throttling the FPS down. + + **Resources** + + The :py:meth:`pie_time.AbstractCard.path_for_resource` method can be used + to get an absolute path to a resource file. The card's resource folder + should be placed along with the module containing the card's class. + + Name of the resource folder can be customized by overriding the + :py:attr:`pie_time.AbstractCard.RESOURCE_FOLDER` attribute. + """ + #: Name of the folder containing the resources + RESOURCE_FOLDER = 'resources' + + def __init__(self): + self._app = None + self._settings = {} + self._surface = None + + def set_app(self, app): + """Binds the card with the *app*.""" + self._app = app + + def set_settings(self, settings): + """Sets *settings* as the card's settings.""" + self._settings = settings + + @property + def width(self): + """The card's surface width. Defaults to the app screen's width.""" + return self._app.screen_size[0] + + @property + def height(self): + """The card's surface height. Defaults to the app screen's height.""" + return self._app.screen_size[1] + + @property + def surface(self): + """ + The cards surface. The surface width and height are defined by the + respective properties of the class. + """ + if self._surface is None: + self._surface = pygame.surface.Surface((self.width, self.height)) + + return self._surface + + @property + def background_color(self): + """ + The background color. Defaults to + :py:attr:`pie_time.PieTime.BACKGROUND_COLOR`. + """ + return self._settings.get( + 'background_color', self._app.BACKGROUND_COLOR + ) + + def path_for_resource(self, resource, folder=None): + """ + Returns an absolute path for *resource*. The optional *folder* + keyword argument allows specifying a subpath. + """ + _subpath = '' + if folder: + _subpath = folder + + module_path = sys.modules[self.__module__].__file__ + + return os.path.join( + os.path.abspath(os.path.dirname(module_path)), + self.RESOURCE_FOLDER, _subpath, resource + ) + + def initialize(self): + """ + Initializes the card. + + The application calls this method right after creating an instance of + the class. + + This method can be used to perform additional initialization on the + card, e.g. loading resources, setting the initial state etc. + + The default implementation does nothing. + """ + pass + + def quit(self): + """ + Initializes the card. + + This method can be used to perform additional cleanup on the + card, e.g. stop threads, free resources etc. + + The default implementation does nothing. + """ + + def show(self): + """ + Shows the card. + + The application calls this method each time the card becomes the + current card. + + This method can be used to reset initial state, e.g. sprite positions. + + The default implementation does nothing. + """ + pass + + def hide(self): + """ + Hides the card. + + The application calls this method each time the card resignes the + current card. + + This method can be used to e.g. stop threads which aren't supposed to + be running when the card isn't being displayed. + + The default implementation does nothing. + """ + pass + + def tick(self): + """ + Ticks the card. + + The application calls this method on the current card in every main + loop iteration. + + This method should be used to perform drawing and other operations + needed to properly display the card on screen. + + Subclasses **must** override this method. + """ + raise NotImplementedError('TODO') diff --git a/pie_time/cards/__init__.py b/pie_time/cards/__init__.py new file mode 100644 index 0000000..02161f3 --- /dev/null +++ b/pie_time/cards/__init__.py @@ -0,0 +1,3 @@ +from .clock import ClockCard +from .picture import PictureCard +from .weather import WeatherCard diff --git a/pie_time/cards/clock.py b/pie_time/cards/clock.py new file mode 100644 index 0000000..1bc18b9 --- /dev/null +++ b/pie_time/cards/clock.py @@ -0,0 +1,154 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2014-2016 Tomek Wójcik +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# + +""" +pie_time.cards.clock +==================== + +This module containse the ClockCard class. +""" + +import datetime + +import pygame + +from pie_time.card import AbstractCard + + +class ClockCard(AbstractCard): + """ + The clock card. + + This card displays a digital clock and date. + + **Settings dictionary keys**: + + * **time_format** (*string*) - time format string (*strftime()* + compatible). Defaults to :py:attr:`pie_time.cards.ClockCard.TIME_FORMAT` + * **time_blink** (*boolean*) - if set to ``True`` the semicolons will + blink. Defaults to ``True``. + * **time_color** (*tuple*) - time text color. Defaults to + :py:attr:`pie_time.cards.ClockCard.GREEN` + * **date_format** (*string*) - date format string (*strftime()* + compatible). Defaults to :py:attr:`pie_time.cards.ClockCard.DATE_FORMAT` + * **date_color** (*tuple*) - date text color. Defaults to + :py:attr:`pie_time.cards.ClockCard.GREEN` + """ + + #: Green color for text + GREEN = (96, 253, 108) + + #: Default time format + TIME_FORMAT = '%I:%M %p' + + #: Default date format + DATE_FORMAT = '%a, %d %b %Y' + + def initialize(self): + self._time_font = pygame.font.Font( + self.path_for_resource('PTM55FT.ttf'), 63 + ) + + self._date_font = pygame.font.Font( + self.path_for_resource('opensans-light.ttf'), 36 + ) + + self._now = None + self._current_interval = 0 + + def _render_time(self, now): + time_format = self._settings.get('time_format', self.TIME_FORMAT) + + if self._settings.get('time_blink', True) and now.second % 2 == 1: + time_format = time_format.replace(':', ' ') + + current_time = now.strftime(time_format) + + text = self._time_font.render( + current_time, True, self._settings.get('time_color', self.GREEN) + ) + + return text + + def _render_date(self, now): + date_format = self._settings.get('date_format', self.DATE_FORMAT) + + current_date = now.strftime(date_format) + + text = self._date_font.render( + current_date, True, self._settings.get('date_color', self.GREEN) + ) + + return text + + def _update_now(self): + if self._now is None: + self._now = datetime.datetime.now() + self._current_interval = 0 + + return True + else: + self._current_interval += self._app._clock.get_time() + + if self._current_interval >= 1000: + self._now = datetime.datetime.now() + self._current_interval = self._current_interval - 1000 + + return True + + return False + + def show(self): + self._now = None + + def tick(self): + now_updated = self._update_now() + + if now_updated: + time_text = self._render_time(self._now) + date_text = self._render_date(self._now) + + time_text_size = time_text.get_size() + date_text_size = date_text.get_size() + + time_text_origin_y = ( + (self.height - time_text_size[1] - date_text_size[1]) / 2.0 + ) + + time_text_rect = ( + (self.width - time_text_size[0]) / 2.0, + time_text_origin_y, + time_text_size[0], + time_text_size[1] + ) + + date_text_rect = ( + (self.width - date_text_size[0]) / 2.0, + time_text_origin_y + time_text_size[1], + date_text_size[0], + date_text_size[1] + ) + + self.surface.fill(self.background_color) + + self.surface.blit(time_text, time_text_rect) + self.surface.blit(date_text, date_text_rect) diff --git a/pie_time/cards/picture.py b/pie_time/cards/picture.py new file mode 100644 index 0000000..a190a7e --- /dev/null +++ b/pie_time/cards/picture.py @@ -0,0 +1,140 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2014-2016 Tomek Wójcik +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# + +""" +pie_time.cards.picture +====================== + +This module containse the PictureCard class. +""" + +import cStringIO +import os +import urlparse + +import pygame +import requests + +from pie_time.card import AbstractCard + + +class PictureCard(AbstractCard): + """ + The picture card. + + This cards displays a picture from list of pre-defined pictures. If more + than one picture is defined, it's changed each time the card transitions + to current card. + + **Settings dictionary keys**: + + * **urls** (*list*) - **required** list of picture URLs. Currently, only + ``file://``, ``http://`` and ``https://`` URL schemes are supported. + """ + + def initialize(self): + self._pictures = [] + self._current_picture_idx = None + self._should_redraw = True + + for url in self._settings['urls']: + self._pictures.append(self._load_picture(url)) + + def _load_picture(self, url): + self._app.logger.debug( + 'PictureCard: Attempting to load picture: %s' % url + ) + + parsed_url = urlparse.urlparse(url) + + surface = None + try: + format = None + if parsed_url.scheme == 'file': + surface = pygame.image.load(parsed_url.path) + + _, ext = os.path.splitext(parsed_url.path) + format = ext.lower() + elif parsed_url.scheme.startswith('http'): + rsp = requests.get(url) + assert rsp.status_code == 200 + + format = rsp.headers['Content-Type'].replace('image/', '') + + surface = pygame.image.load( + cStringIO.StringIO(rsp.content), 'picture.%s' % format + ) + + if surface and format: + if format.lower().endswith('png'): + surface = surface.convert_alpha(self._app.screen) + else: + surface = surface.convert(self._app.screen) + except Exception as exc: + self._app.logger.error( + 'PictureCard: Could not load picture: %s' % url, exc_info=True + ) + + return surface + + def show(self): + if len(self._pictures) == 0: + self._current_picture_idx = None + elif len(self._pictures) == 1: + self._current_picture_idx = 0 + else: + if self._current_picture_idx is None: + self._current_picture_idx = 0 + else: + new_picture_idx = self._current_picture_idx + 1 + if new_picture_idx >= len(self._pictures): + new_picture_idx = 0 + + self._app.logger.debug( + 'PictureCard: Picture transition %d -> %d' % ( + self._current_picture_idx, new_picture_idx + ) + ) + + self._current_picture_idx = new_picture_idx + + self._should_redraw = True + + def tick(self): + if self._should_redraw: + self.surface.fill(self.background_color) + + if self._current_picture_idx is not None: + picture = self._pictures[self._current_picture_idx] + picture_size = picture.get_size() + + picture_rect = picture.get_rect() + if picture_size != self._app.screen_size: + picture_rect = ( + (self.width - picture_size[0]) / 2.0, + (self.height - picture_size[1]) / 2.0, + picture_size[0], picture_size[1] + ) + + self.surface.blit(picture, picture_rect) + + self._should_redraw = False diff --git a/pie_time/cards/resources/PTM55FT.ttf b/pie_time/cards/resources/PTM55FT.ttf new file mode 100755 index 0000000000000000000000000000000000000000..f580123617dbf5c57488185920a8184fa64bf780 GIT binary patch literal 185912 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�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%0AG%b#%#Weyp=oz<}IGPqm z)8c4aT%)1Wt!Z(MiMFk2@iJ>#98HU(X>l|yj;6)Yv^bg;N7LeHS{zM_Yxd#ySkvN~ zeHg82+}v^bg;*NE&CYg!yli=%0AG%cHosL)|1w>IGPqm)8c4a98HU( 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 +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# + +""" +pie_time.cards.weather +====================== + +This module containse the WeatherCard class. +""" + +from threading import Timer + +import pygame +import requests + +from pie_time.card import AbstractCard + +URL_TEMPLATE = ( + 'http://api.openweathermap.org/data/2.5/weather?q=%s&units=%s&APPID=%s' +) + + +class WeatherCard(AbstractCard): + """ + The weather card. + + This cards displays the current weather for a selected city. The weather + information is obtained from OpenWeatherMap. + + **Settings dictionary keys**: + + * **api_key** (*string*) - **required** API key. + * **city** (*string*) - **required** name of the city. + * **units** (*string*) - units name (``metric`` or ``imperial``). Defaults + to :py:attr:`pie_time.cards.WeatherCard.UNITS` + * **refresh_interval** (*int*) - refresh interval in seconds. Defaults to + :py:attr:`pie_time.cards.WeatherCard.REFRESH_INTERVAL` + * **city_color** (*tuple*) - city text color. Defaults to + :py:attr:`pie_time.cards.WeatherCard.WHITE` + * **icon_color** (*tuple*) - icon text color. Defaults to + :py:attr:`pie_time.cards.WeatherCard.WHITE` + * **temperature_color** (*tuple*) - temperature text color. Defaults to + :py:attr:`pie_time.cards.WeatherCard.WHITE` + * **conditions_color** (*tuple*) - conditions text color. Defaults to + :py:attr:`pie_time.cards.WeatherCard.WHITE` + """ + + #: Default units + UNITS = 'metric' + + #: Default refresh interval + REFRESH_INTERVAL = 600 + + #: White color for text + WHITE = (255, 255, 255) + + WEATHER_CODE_TO_ICON = { + '01d': u'', + '01n': u'', + '02d': u'', + '02n': u'', + '03d': u'', + '03n': u'', + '04d': u'', + '04n': u'', + '09d': u'', + '09n': u'', + '10d': u'', + '10n': u'', + '11d': u'', + '11n': u'', + '13d': u'', + '13n': u'', + '50d': u'', + '50n': u'' + } + ICON_SPACING = 24 + + def initialize(self, refresh=True): + assert 'api_key' in self._settings,\ + 'Configuration error: missing API key' + assert 'city' in self._settings, 'Configuration error: missing city' + + self._text_font = pygame.font.Font( + self.path_for_resource('opensans-light.ttf'), 30 + ) + + self._temp_font = pygame.font.Font( + self.path_for_resource('opensans-light.ttf'), 72 + ) + + self._icon_font = pygame.font.Font( + self.path_for_resource('linea-weather-10.ttf'), 128 + ) + + self._timer = None + self._current_conditions = None + self._should_redraw = True + + if refresh: + self._refresh_conditions() + + def _refresh_conditions(self): + self._app.logger.debug('Refreshing conditions.') + self._timer = None + + try: + rsp = requests.get( + URL_TEMPLATE % ( + self._settings['city'], + self._settings.get('units', self.UNITS), + self._settings['api_key'] + ) + ) + + if rsp.status_code != 200: + self._app.logger.error( + 'WeatherCard: Received HTTP %d' % rsp.status_code + ) + else: + try: + payload = rsp.json() + self._current_conditions = { + 'conditions': payload['weather'][0]['main'], + 'icon': payload['weather'][0].get('icon', None), + 'temperature': payload['main']['temp'] + } + self._should_redraw = True + except: + self._app.logger.error( + 'WeatherCard: ERROR!', exc_info=True + ) + except: + self._app.logger.error('WeatherCard: ERROR!', exc_info=True) + + self._timer = Timer( + self._settings.get('refresh_interval', self.REFRESH_INTERVAL), + self._refresh_conditions + ) + self._timer.start() + + def _render_city(self): + city_text = self._text_font.render( + self._settings['city'], True, + self._settings.get('city_color', self.WHITE) + ) + + return city_text + + def _render_conditions(self): + conditions_text = self._text_font.render( + self._current_conditions['conditions'].capitalize(), + True, self._settings.get('conditions_color', self.WHITE) + ) + + return conditions_text + + def _render_icon(self): + icon = self._current_conditions['icon'] + weather_icon = None + + if icon in self.WEATHER_CODE_TO_ICON: + weather_icon = self._icon_font.render( + self.WEATHER_CODE_TO_ICON[icon], + True, self._settings.get('icon_color', self.WHITE) + ) + + return weather_icon + + def _render_temperature(self): + temp_text = self._temp_font.render( + u'%d°' % self._current_conditions['temperature'], + True, + self._settings.get('temperature_color', self.WHITE) + ) + + return temp_text + + def quit(self): + if self._timer is not None: + self._timer.cancel() + + def tick(self): + if self._should_redraw: + self.surface.fill(self.background_color) + + city_text = self._render_city() + city_text_size = city_text.get_size() + city_text_rect = ( + (self.width - city_text_size[0]) / 2.0, + 0, + city_text_size[0], + city_text_size[1] + ) + self.surface.blit(city_text, city_text_rect) + + if self._current_conditions: + conditions_text = self._render_conditions() + conditions_text_size = conditions_text.get_size() + conditions_text_rect = ( + (self.width - conditions_text_size[0]) / 2.0, + self.height - conditions_text_size[1], + conditions_text_size[0], + conditions_text_size[1] + ) + self.surface.blit(conditions_text, conditions_text_rect) + + icon = self._render_icon() + has_icon = (icon is not None) + + temp_text = self._render_temperature() + temp_text_size = temp_text.get_size() + + if has_icon: + icon_size = icon.get_size() + icon_origin_x = ( + ( + self.width - ( + icon_size[0] + self.ICON_SPACING + + temp_text_size[0] + ) + ) / 2.0 + ) + icon_origin_y = ( + city_text_size[1] + ( + self.height - conditions_text_size[1] - + city_text_size[1] - icon_size[1] + ) / 2.0 + ) + icon_rect = ( + icon_origin_x, + icon_origin_y, + icon_size[0], + icon_size[1] + ) + + self.surface.blit(icon, icon_rect) + + temp_text_origin_y = ( + city_text_size[1] + ( + self.height - conditions_text_size[1] - + city_text_size[1] - temp_text_size[1] + ) / 2.0 + ) + + if has_icon: + temp_text_origin_x = ( + icon_rect[0] + icon_size[0] + + self.ICON_SPACING + ) + temp_text_rect = ( + temp_text_origin_x, + temp_text_origin_y, + temp_text_size[0], + temp_text_size[1] + ) + else: + temp_text_rect = ( + (self.width - temp_text_size[0]) / 2.0, + temp_text_origin_y, + temp_text_size[0], + temp_text_size[1] + ) + + self.surface.blit(temp_text, temp_text_rect) + + self._should_redraw = False diff --git a/pie_time/scripts/__init__.py b/pie_time/scripts/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pie_time/scripts/pie_time.py b/pie_time/scripts/pie_time.py new file mode 100644 index 0000000..e053fd6 --- /dev/null +++ b/pie_time/scripts/pie_time.py @@ -0,0 +1,104 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2014-2016 Tomek Wójcik +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# + +import ConfigParser +import imp +import os +import sys +import traceback + +RET_OK = 0 +RET_NO_ARGS = 1 +RET_ERROR = 99 + +CONFIG_SECTION_PIE_TIME = 'PieTime' +CONFIG_SECTION_SDL = 'SDL' + +SDL_DEFAULTS = { + 'VIDEODRIVER': None +} + +def _find_module(name, search_path): + import_path = name.split('.', 1) + + mod_f, mod_path, mod_desc = imp.find_module(import_path[0], search_path) + if mod_desc[2] == imp.PKG_DIRECTORY: + return _find_module( + import_path[1], [os.path.abspath(mod_path)] + ) + else: + return mod_f, mod_path, mod_desc + +def main(): + try: + config_file_path = sys.argv[1] + except IndexError: + print 'usage: %s [CONFIG_FILE]' % sys.argv[0] + return RET_NO_ARGS + + config = ConfigParser.SafeConfigParser() + config.optionxform = str + config.read(config_file_path) + + app_spec = config.get(CONFIG_SECTION_PIE_TIME, 'app_module', True) + try: + app_module, app_obj = app_spec.split(':') + except ValueError: + print "%s: failed to find application '%s'" % ( + sys.argv[0], app_spec + ) + return RET_ERROR + + mod_f = None + result = RET_OK + try: + mod_search_path = [os.getcwd()] + sys.path + mod_f, mod_path, mod_desc = _find_module(app_module, mod_search_path) + + mod = imp.load_module(app_module, mod_f, mod_path, mod_desc) + app = getattr(mod, app_obj) + + if config.has_option(CONFIG_SECTION_PIE_TIME, 'log_path'): + app.log_path = config.get(CONFIG_SECTION_PIE_TIME, 'log_path') + + sdl_config = dict(SDL_DEFAULTS) + if config.has_section(CONFIG_SECTION_SDL): + sdl_config.update({ + x[0]: x[1] for x in config.items(CONFIG_SECTION_SDL) + }) + + for k, v in sdl_config.iteritems(): + if v: + os.environ['SDL_%s' % k] = v + + result = app.run(standalone=False) + except: + traceback.print_exc() + result = RET_ERROR + finally: + if mod_f: + mod_f.close() + + return result + +if __name__ == '__main__': + sys.exit(main()) diff --git a/requirements-dev.txt b/requirements-dev.txt new file mode 100644 index 0000000..bb6b3d8 --- /dev/null +++ b/requirements-dev.txt @@ -0,0 +1,3 @@ +mock==1.3.0 +nose==1.3.7 +Sphinx==1.3.5 diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..c792661 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +pygame>=1.9.1 +requests>=2.4.1 diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..d83ca91 --- /dev/null +++ b/setup.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python2.7 +# -*- coding: utf-8 -*- +# Copyright (c) 2014-2016 Tomek Wójcik +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# + +import codecs +from setuptools import setup + +import pie_time + +with codecs.open('README.rst', 'r', 'utf-8') as desc_f: + long_description = desc_f.read() + +with codecs.open('requirements.txt', 'r', 'utf-8') as requirements_f: + requirements = requirements_f.read().split('\n') + +SCRIPTS = [ + 'pie_time = pie_time.scripts.pie_time:main' +] + +DOWNLOAD_URL = ( + 'https://git.bthlabs.pl/tomekwojcik/pie-time/archive/v%s.tar.gz' % + pie_time.__version__ +) + +setup( + name="pie_time", + version=pie_time.__version__, + packages=[ + 'pie_time', + 'pie_time.cards', + 'pie_time.scripts' + ], + include_package_data=True, + test_suite='nose.collector', + zip_safe=False, + platforms='any', + tests_require=[ + 'nose', + ], + author=pie_time.__author__.encode('utf-8'), + author_email='tomek@bthlabs.pl', + maintainer=pie_time.__author__.encode('utf-8'), + maintainer_email='tomek@bthlabs.pl', + url='https://pie-time.bthlabs.pl/', + download_url=DOWNLOAD_URL, + description='Desk clock for your Raspberry Pi.', + long_description=long_description, + license='https://git.bthlabs.pl/tomekwojcik/pie-time/src/master/LICENSE', + classifiers=[], + install_requires=requirements, + entry_points={ + 'console_scripts': SCRIPTS + } +) diff --git a/tests/test_abstract_card.py b/tests/test_abstract_card.py new file mode 100644 index 0000000..6538358 --- /dev/null +++ b/tests/test_abstract_card.py @@ -0,0 +1,89 @@ +# -*- coding: utf-8 -*- + +import mock +import os +import pygame + +from pie_time import application as app_module +from pie_time.application import PieTime +from pie_time.card import AbstractCard + + +class Test_AbstractCard(object): + def _dummy_card(self, **settings): + app = PieTime(None) + card = AbstractCard() + card.set_app(app) + card.set_settings(settings) + + return card + + def test_init(self): + card = AbstractCard() + assert card._app is None + assert card._settings == {} + assert card._surface is None + + def test_set_app(self): + card = AbstractCard() + app = mock.Mock(spec=PieTime) + card.set_app(app) + assert card._app == app + + def test_set_settings(self): + card = AbstractCard() + settings = {'spam': 'eggs'} + card.set_settings(settings) + assert card._settings == settings + + def test_width(self): + card = self._dummy_card() + assert card.width == card._app.screen_size[0] + + def test_height(self): + card = self._dummy_card() + assert card.height == card._app.screen_size[1] + + def test_surface(self): + fake_surface = mock.Mock(spec=pygame.surface.Surface) + + with mock.patch.object(app_module.pygame.surface, 'Surface', + return_value=fake_surface): + card = self._dummy_card() + assert card.surface == fake_surface + assert card._surface == card.surface + app_module.pygame.surface.Surface.assert_called_with(( + card.width, card.height + )) + + def test_background_color(self): + card = self._dummy_card() + assert card.background_color == card._app.BACKGROUND_COLOR + + def test_background_color_override(self): + card = self._dummy_card(background_color=(255, 255, 255)) + assert card.background_color == (255, 255, 255) + + def test_path_for_resource(self): + card = self._dummy_card() + + spam_path = card.path_for_resource('spam') + assert os.path.isabs(spam_path) + assert card.RESOURCE_FOLDER in spam_path + assert spam_path.endswith('spam') + + spam_eggs_path = card.path_for_resource('spam', folder='eggs') + assert os.path.isabs(spam_eggs_path) + assert card.RESOURCE_FOLDER in spam_eggs_path + assert 'eggs' in spam_eggs_path + assert spam_eggs_path.endswith('spam') + + def test_tick(self): + try: + card = self._dummy_card() + card.tick() + except Exception as exc: + assert isinstance(exc, RuntimeError) + assert exc.args[0] == 'TODO' + else: + assert False, 'Nothing was raised :(' diff --git a/tests/test_application.py b/tests/test_application.py new file mode 100644 index 0000000..e551376 --- /dev/null +++ b/tests/test_application.py @@ -0,0 +1,744 @@ +# -*- coding: utf-8 -*- + +import datetime +import logging +import os +import sys + +import mock +import pygame + +from pie_time import application as app_module +from pie_time.application import logging as app_logging +from pie_time.application import EVENT_QUIT, EVENT_CLICK_TO_UNBLANK,\ + EVENT_CLICK_TO_PREV_CARD, EVENT_CLICK_TO_NEXT_CARD, RET_OK, RET_ERROR,\ + PieTime +from pie_time.card import AbstractCard + + +class DummyCard(AbstractCard): + def tick(self): + pass + + def initialize(self): + self._surface = mock.Mock(spec=pygame.surface.Surface) + + +class FakeTimer(object): + def __init__(self, step=1, start=None): + if start is None: + self.n = 0 - step + else: + self.n = start + self._step = step + + def __call__(self): + self.n += self._step + return self.n + + +def _now(*args): + return datetime.datetime(*args) + + +class Test_Application(object): + def _dummy_deck(self): + return [mock.Mock(spec=DummyCard)] + + def _dummy_blanker_schedule(self): + return (datetime.timedelta(hours=1), datetime.timedelta(hours=2)) + + def _mocked_app(self, **kwargs): + mocked_app = PieTime(self._dummy_deck(), **kwargs) + mocked_app.init_pygame = mock.Mock() + mocked_app.get_screen = mock.Mock( + side_effect=lambda: mock.Mock(spec=pygame.Surface) + ) + mocked_app._should_blank = mock.Mock(return_value=False) + mocked_app._blank = mock.Mock() + mocked_app._unblank = mock.Mock() + mocked_app.fill_screen = mock.Mock() + mocked_app._clock = mock.Mock(spec=pygame.time.Clock) + mocked_app.destroy_cards = mock.Mock() + mocked_app.quit_pygame = mock.Mock() + mocked_app._start_clock = mock.Mock() + mocked_app._setup_output_stream = mock.Mock() + mocked_app._setup_logging = mock.Mock() + mocked_app._logger = mock.Mock(spec=logging.Logger) + + def init_cards(*args, **kwargs): + PieTime.init_cards(mocked_app) + + mocked_app.init_cards = mock.Mock(side_effect=init_cards) + + def transition_cards(*args, **kwargs): + mocked_app._current_card_idx = 0 + mocked_app._current_card_time = 0 + + mocked_app._transition_cards = mock.Mock( + side_effect=transition_cards + ) + + return mocked_app + + def _make_app(self, *args, **kwargs): + new_app = PieTime(*args, **kwargs) + new_app._logger = mock.Mock(spec=logging.Logger) + + return new_app + + def test_init_default_settings(self): + deck = self._dummy_deck() + app = self._make_app(deck) + + assert app._deck == deck + assert app.screen is None + assert app.screen_size == (320, 240) + assert app.events == [] + assert app.log_path is None + assert app._fps == 20 + assert app._verbose is False + assert app._blanker_schedule is None + assert app._click_to_unblank_interval is None + assert app._click_to_transition is True + assert app._clock is None + assert app._cards == [] + assert app._is_blanked is False + assert app._current_card_idx is None + assert app._current_card_time is None + assert app._should_quit is False + assert len(app._internal_events) == 0 + assert app._ctu_timer is None + assert app._output_stream is None + + assert app._ctt_region_prev.x == 0 + assert app._ctt_region_prev.y == 210 + assert app._ctt_region_prev.width == 30 + assert app._ctt_region_prev.height == 30 + + assert app._ctt_region_next.x == 290 + assert app._ctt_region_next.y == 210 + assert app._ctt_region_next.width == 30 + assert app._ctt_region_next.height == 30 + + def test_init_override_settings(self): + deck = self._dummy_deck() + blanker_schedule = self._dummy_blanker_schedule() + + app = self._make_app( + deck, screen_size=(640, 480), fps=60, verbose=True, + blanker_schedule=blanker_schedule, + click_to_unblank_interval=10, click_to_transition=False, + log_path='/path/to/log_file.txt' + ) + + assert app.screen_size == (640, 480) + assert app.log_path == '/path/to/log_file.txt' + assert app._fps == 60 + assert app._verbose is True + assert app._blanker_schedule == blanker_schedule + assert app._click_to_unblank_interval == 10 + assert app._click_to_transition is False + + def test_should_blank_scheduled(self): + blanker_schedule = self._dummy_blanker_schedule() + + app = self._make_app(self._dummy_deck()) + assert app._should_blank(now=_now(2014, 10, 15, 9)) is False + + app = self._make_app( + self._dummy_deck(), blanker_schedule=blanker_schedule + ) + assert app._should_blank(now=_now(2014, 10, 15, 0, 0, 0)) is False + assert app._should_blank(now=_now(2014, 10, 15, 1, 0, 0)) is True + assert app._should_blank(now=_now(2014, 10, 15, 1, 30, 0)) is True + assert app._should_blank(now=_now(2014, 10, 15, 1, 59, 59)) is True + assert app._should_blank(now=_now(2014, 10, 15, 2, 0, 0)) is False + assert app._should_blank(now=_now(2014, 10, 15, 9, 0, 0)) is False + + blanker_schedule = ( + datetime.timedelta(hours=23), datetime.timedelta(hours=6) + ) + app = self._make_app( + self._dummy_deck(), blanker_schedule=blanker_schedule + ) + assert app._should_blank(now=_now(2014, 10, 15, 0, 0, 0)) is True + assert app._should_blank(now=_now(2014, 10, 15, 5, 59, 59)) is True + assert app._should_blank(now=_now(2014, 10, 15, 6, 0, 0)) is False + assert app._should_blank(now=_now(2014, 10, 15, 12, 0, 0)) is False + assert app._should_blank(now=_now(2014, 10, 15, 22, 59, 59)) is False + assert app._should_blank(now=_now(2014, 10, 15, 23, 0, 0)) is True + + def test_should_blank_ctu(self): + ctu = 10 + + app = self._make_app(self._dummy_deck()) + app._has_click_to_unblank_event = mock.Mock(return_value=True) + assert app._should_blank() is False + assert app._ctu_timer is None + + app = self._make_app( + self._dummy_deck(), + blanker_schedule=self._dummy_blanker_schedule(), + click_to_unblank_interval=ctu + ) + app._is_blanked = True + app._has_click_to_unblank_event = mock.Mock(return_value=True) + assert app._should_blank(now=_now(2014, 10, 15, 1, 0, 0)) is False + assert app._ctu_timer == ctu + + app = self._make_app( + self._dummy_deck(), + blanker_schedule=self._dummy_blanker_schedule(), + click_to_unblank_interval=ctu + ) + app._is_blanked = True + app._ctu_timer = ctu + app._has_click_to_unblank_event = mock.Mock(return_value=False) + + app._clock = mock.Mock(spec=pygame.time.Clock) + app._clock.get_time = mock.Mock(return_value=1 * 1000) + + assert app._should_blank(now=_now(2014, 10, 15, 1, 0, 0)) is False + assert app._ctu_timer == ctu - 1 + + app = self._make_app( + self._dummy_deck(), + blanker_schedule=self._dummy_blanker_schedule(), + click_to_unblank_interval=ctu + ) + app._is_blanked = True + app._ctu_timer = ctu + app._has_click_to_unblank_event = mock.Mock(return_value=False) + + app._clock = mock.Mock(spec=pygame.time.Clock) + app._clock.get_time = mock.Mock(return_value=ctu * 1000) + + assert app._should_blank(now=_now(2014, 10, 15, 1, 0, 0)) is True + assert app._ctu_timer is None + + def test_blank(self): + app = self._make_app(self._dummy_deck()) + app.screen = mock.Mock(spec=pygame.surface.Surface) + app.will_blank = mock.Mock() + + app._blank() + assert app._is_blanked is True + assert app.will_blank.called is True + app.screen.fill.assert_called_with(PieTime.BLANK_COLOR) + + def test_unblank(self): + app = self._make_app(self._dummy_deck()) + app.init_cards() + app._is_blanked = True + app.will_unblank = mock.Mock() + + app._unblank() + assert app._is_blanked is False + assert app.will_unblank.called is True + assert app._cards[0][0].show.call_count == 1 + + def test_transition_cards(self): + deck = [ + (mock.Mock(spec=DummyCard), 1), + (mock.Mock(spec=DummyCard), 1) + ] + + app = self._make_app(self._dummy_deck()) + app.init_cards() + app._transition_cards() + + assert app._current_card_idx == 0 + assert not app._cards[0][0].hide.called + assert app._cards[0][0].show.call_count == 1 + + app = self._make_app(deck) + app._clock = mock.Mock(spec=pygame.time.Clock) + + timer = FakeTimer(step=2, start=0) + app._clock.get_time = mock.Mock( + side_effect=lambda: timer() * 1000.0 + ) + + app.init_cards() + app._current_card_idx = 0 + app._current_card_time = 0 + + app._transition_cards() + assert app._current_card_idx == 1 + assert app._cards[0][0].hide.call_count == 1 + assert app._cards[1][0].show.call_count == 1 + + app._transition_cards() + assert app._current_card_idx == 0 + assert app._cards[0][0].show.call_count == 1 + assert app._cards[1][0].hide.call_count == 1 + + def test_transition_cards_forced(self): + deck = [ + (mock.Mock(spec=DummyCard), 1), + (mock.Mock(spec=DummyCard), 1) + ] + + app = self._make_app(deck) + app._clock = mock.Mock(spec=pygame.time.Clock) + + timer = FakeTimer(step=2, start=0) + app._clock.get_time = mock.Mock( + side_effect=lambda: timer() + ) + + app.init_cards() + app._current_card_idx = 0 + app._current_card_time = 0 + + app._transition_cards(direction=1, force=True) + assert app._current_card_idx == 1 + + app._transition_cards(direction=1, force=True) + assert app._current_card_idx == 0 + + app._transition_cards(direction=-1, force=True) + assert app._current_card_idx == 1 + + app._transition_cards(direction=-1, force=True) + assert app._current_card_idx == 0 + + def test_get_events_quit_pygame(self): + new_event_get = mock.Mock(return_value=[ + pygame.event.Event(pygame.QUIT) + ]) + + app = self._make_app(self._dummy_deck()) + with mock.patch.object(app_module.pygame.event, 'get', + new=new_event_get): + app._get_events() + assert app._internal_events == set([EVENT_QUIT]) + + def test_get_events_quit_key(self): + new_event_get = mock.Mock(return_value=[ + pygame.event.Event(pygame.KEYDOWN, key=PieTime.KEY_QUIT) + ]) + + app = self._make_app(self._dummy_deck()) + with mock.patch.object(app_module.pygame.event, 'get', + new=new_event_get): + app._get_events() + assert app._internal_events == set([EVENT_QUIT]) + + def test_get_events_click_to_unblank(self): + new_event_get = mock.Mock(return_value=[ + pygame.event.Event(pygame.MOUSEBUTTONDOWN, pos=(160, 120)) + ]) + + app = self._make_app(self._dummy_deck(), click_to_unblank_interval=10) + with mock.patch.object(app_module.pygame.event, 'get', + new=new_event_get): + app._is_blanked = False + app._get_events() + assert app._internal_events == set() + + app._is_blanked = True + app._get_events() + assert app._internal_events == set([EVENT_CLICK_TO_UNBLANK]) + + def test_get_events_click_to_prev_card(self): + new_event_get = mock.Mock(return_value=[ + pygame.event.Event(pygame.MOUSEBUTTONDOWN, pos=(10, 230)) + ]) + + app = self._make_app(self._dummy_deck(), click_to_transition=True) + with mock.patch.object(app_module.pygame.event, 'get', + new=new_event_get): + app._is_blanked = False + app._get_events() + assert app._internal_events == set([EVENT_CLICK_TO_PREV_CARD]) + + app._is_blanked = True + app._get_events() + assert EVENT_CLICK_TO_PREV_CARD not in app._internal_events + + app._click_to_transition = False + app._is_blanked = False + app._get_events() + assert EVENT_CLICK_TO_PREV_CARD not in app._internal_events + + def test_get_events_click_to_next_card(self): + new_event_get = mock.Mock(return_value=[ + pygame.event.Event(pygame.MOUSEBUTTONDOWN, pos=(310, 230)) + ]) + + app = self._make_app(self._dummy_deck(), click_to_transition=True) + with mock.patch.object(app_module.pygame.event, 'get', + new=new_event_get): + app._is_blanked = False + app._get_events() + assert app._internal_events == set([EVENT_CLICK_TO_NEXT_CARD]) + + app._is_blanked = True + app._get_events() + assert EVENT_CLICK_TO_NEXT_CARD not in app._internal_events + + app._click_to_transition = False + app._is_blanked = False + app._get_events() + assert EVENT_CLICK_TO_NEXT_CARD not in app._internal_events + + def test_get_events_other_events(self): + events = [ + pygame.event.Event(pygame.MOUSEBUTTONDOWN, pos=(160, 120)), + pygame.event.Event(pygame.KEYDOWN, key=pygame.K_RETURN) + ] + new_event_get = mock.Mock(return_value=events) + + app = self._make_app(self._dummy_deck(), click_to_transition=True) + with mock.patch.object(app_module.pygame.event, 'get', + new=new_event_get): + app._is_blanked = False + app._get_events() + assert app._internal_events == set() + assert app.events == events + + def test_has_quit_event(self): + app = self._make_app(self._dummy_deck()) + assert app._has_quit_event() is False + + app._internal_events.add(EVENT_QUIT) + assert app._has_quit_event() is True + + def test_has_click_to_unblank_event(self): + app = self._make_app(self._dummy_deck(), click_to_unblank_interval=10) + assert app._has_click_to_unblank_event() is False + + app._internal_events.add(EVENT_CLICK_TO_UNBLANK) + assert app._has_click_to_unblank_event() is True + + def test_start_clock(self): + app = self._make_app(self._dummy_deck()) + + fake_clock = mock.Mock(spec=pygame.time.Clock) + with mock.patch.object(app_module.pygame.time, 'Clock', + return_value=fake_clock): + app._start_clock() + + assert app_module.pygame.time.Clock.called is True + assert app._clock == fake_clock + + def test_setup_output_stream_no_log_path(self): + deck = self._dummy_deck() + + with mock.patch.object(PieTime, '_STREAM_FACTORY'): + with mock.patch.object(PieTime, '_setup_logging'): + app = self._make_app(deck, log_path=None) + app._setup_output_stream() + + assert app._output_stream == PieTime._DEFAULT_OUTPUT_STREAM + assert PieTime._STREAM_FACTORY.called is False + + def test_setup_output_stream_with_log_path(self): + deck = self._dummy_deck() + fake_file = mock.Mock(spec=file) + + with mock.patch.object(PieTime, '_STREAM_FACTORY', new=fake_file): + with mock.patch.object(PieTime, '_setup_logging'): + app = self._make_app(deck, log_path='/path/to/log_file.txt') + app._setup_output_stream() + + PieTime._STREAM_FACTORY.assert_called_with(app.log_path, 'a') + assert app._output_stream != fake_file + + def test_setup_logging_silent(self): + deck = self._dummy_deck() + + fake_logger = mock.Mock(spec=logging.Logger) + fake_requests_logger = mock.Mock(spec=logging.Logger) + fake_handler = mock.Mock(spec=logging.StreamHandler) + fake_formatter = mock.Mock(spec=logging.Formatter) + + fake_requests_logger.handlers = ['spam', 'eggs'] + fake_requests_logger.removeHandler = mock.Mock() + + def fake_getLogger(name): + if name == 'PieTime': + return fake_logger + elif name == 'requests': + return fake_requests_logger + else: + return None + + with mock.patch.object(app_logging, 'getLogger', + side_effect=fake_getLogger): + with mock.patch.object(app_logging, + 'StreamHandler', return_value=fake_handler): + with mock.patch.object(app_logging, + 'Formatter', + return_value=fake_formatter): + app = self._make_app(deck, verbose=False) + app._output_stream = 'spam' + app._setup_logging() + + fake_logger.setLevel.assert_called_with(logging.INFO) + fake_requests_logger.setLevel.assert_called_with( + logging.WARNING + ) + + app_logging.StreamHandler.assert_called_with( + app._output_stream + ) + + assert app_logging.Formatter.called is True + + fake_handler.setFormatter.assert_called_with( + fake_formatter + ) + + fake_logger.addHandler.assert_called_with(fake_handler) + + assert fake_requests_logger.removeHandler.call_count == 2 + fake_requests_logger.removeHandler.assert_any_call('spam') + fake_requests_logger.removeHandler.assert_any_call('eggs') + + fake_requests_logger.addHandler.assert_called_with( + fake_handler + ) + + def test_setup_logging_verbose(self): + deck = self._dummy_deck() + + fake_logger = mock.Mock(spec=logging.Logger) + + fake_requests_logger = mock.Mock(spec=logging.Logger) + fake_requests_logger.handlers = [] + + def fake_getLogger(name): + if name == 'PieTime': + return fake_logger + elif name == 'requests': + return fake_requests_logger + else: + return None + + with mock.patch.object(app_logging, 'getLogger', + side_effect=fake_getLogger): + with mock.patch.object(app_logging, 'StreamHandler'): + with mock.patch.object(app_logging, 'Formatter'): + app = self._make_app(deck, verbose=True) + app._output_stream = 'spam' + app._setup_logging() + + fake_logger.setLevel.assert_called_with(logging.DEBUG) + assert fake_requests_logger.setLevel.called is False + + def test_logger(self): + app = self._make_app(self._dummy_deck()) + assert app.logger is not None + + def test_init_pygame(self): + app = self._make_app(self._dummy_deck()) + + with mock.patch.object(app_module.pygame, 'init'): + with mock.patch.object(app_module.pygame.mouse, 'set_visible'): + app.init_pygame() + assert app_module.pygame.init.called + app_module.pygame.mouse.set_visible.assert_called_with(False) + assert app._clock is None + + def test_quit_pygame(self): + app = self._make_app(self._dummy_deck()) + + with mock.patch.object(app_module.pygame, 'quit'): + app.quit_pygame() + assert app_module.pygame.quit.called + assert app._clock is None + + def test_init_cards(self): + deck = [ + mock.Mock(spec=DummyCard), + (mock.Mock(spec=DummyCard), 10), + (mock.Mock(spec=DummyCard), 20, {'spam': 'eggs'}) + ] + + app = self._make_app(deck) + app.init_cards() + + assert len(app._cards) == 3 + + app._cards[0][0].set_app.assert_called_with(app) + app._cards[0][0].set_settings.assert_called_with({}) + assert app._cards[0][0].initialize.called + assert not app._cards[0][0].show.called + assert app._cards[0][1] == PieTime.CARD_INTERVAL + + app._cards[1][0].set_app.assert_called_with(app) + app._cards[1][0].set_settings.assert_called_with({}) + assert app._cards[1][0].initialize.called + assert not app._cards[1][0].show.called + assert app._cards[1][1] == 10 + + app._cards[2][0].set_app.assert_called_with(app) + app._cards[2][0].set_settings.assert_called_with({'spam': 'eggs'}) + assert app._cards[2][0].initialize.called + assert not app._cards[2][0].show.called + assert app._cards[2][1] == 20 + + assert app._current_card_idx is None + assert app._current_card_time is None + + def test_destroy_cards(self): + with mock.patch.object(DummyCard, 'quit'): + app = self._make_app([DummyCard]) + + app.init_cards() + app.destroy_cards() + + assert len(app._cards) == 0 + assert DummyCard.quit.called + + def test_get_screen(self): + with mock.patch.object(app_module.pygame.display, 'set_mode', + return_value='spam'): + app = self._make_app(self._dummy_deck()) + screen = app.get_screen() + + assert screen == 'spam' + app_module.pygame.display.set_mode.\ + assert_called_with(app.screen_size) + + def test_fill_screen(self): + app = self._make_app(self._dummy_deck()) + app.screen = mock.Mock(pygame.Surface) + + app.fill_screen() + app.screen.fill.assert_called_with(PieTime.BACKGROUND_COLOR) + + def test_run(self): + app = self._mocked_app() + + def new_start_clock(*args, **kwargs): + app._clock.tick = mock.Mock(side_effect=lambda x: app.quit()) + app._start_clock = mock.Mock(side_effect=new_start_clock) + + new_event_get = mock.Mock(return_value=[]) + + with mock.patch.object(app_module.sys, 'exit'): + with mock.patch.object(app_module.pygame.event, 'get', + new=new_event_get): + with mock.patch.object(app_module.pygame.display, 'flip'): + app.run() + + assert app._setup_output_stream.called is True + assert app._setup_logging.called is True + + assert app.init_pygame.called + assert app.get_screen.called + assert app.screen is not None + assert app.init_cards.called + assert app._start_clock.called + assert app_module.pygame.event.get.called + assert app._should_blank.called + assert app._unblank.called + assert not app._blank.called + assert app._transition_cards.called + assert app._cards[0][0].tick.called + assert app.fill_screen.called + app.screen.blit.assert_called_with( + app._cards[0][0].surface, + (0, 0, app._cards[0][0].width, app._cards[0][0].height) + ) + assert pygame.display.flip.called + app._clock.tick.assert_called_with(app._fps) + assert app.destroy_cards.called + assert app.quit_pygame.called + app_module.sys.exit.assert_called_with(RET_OK) + + def test_run_handling_exception(self): + app = self._mocked_app() + app._clock.tick = mock.Mock(side_effect=RuntimeError('spam')) + + new_event_get = mock.Mock(return_value=[]) + + with mock.patch.object(app_module.sys, 'exit'): + with mock.patch.object(app_module.pygame.event, 'get', + new=new_event_get): + with mock.patch.object(app_module.pygame.display, 'flip'): + app.run() + sys.exit.assert_called_with(RET_ERROR) + + def test_run_handling_quit_event(self): + app = self._mocked_app() + app._get_events = mock.Mock() + app._has_quit_event = mock.Mock(return_value=True) + + with mock.patch.object(app_module.sys, 'exit'): + with mock.patch.object(app_module.pygame.display, 'flip'): + app.run() + sys.exit.assert_called_with(RET_OK) + + def test_run_blanking(self): + app = self._mocked_app() + + timer = FakeTimer() + + def should_blank(*args, **kwargs): + return (timer.n % 2 == 1) + + app._should_blank = mock.Mock(side_effect=should_blank) + + def clock_tick(*args, **kwargs): + timer() + if timer.n == 3: + app.quit() + + app._clock.tick = mock.Mock(side_effect=clock_tick) + + new_event_get = mock.Mock(return_value=[]) + + with mock.patch.object(app_module.sys, 'exit'): + with mock.patch.object(app_module.pygame.event, 'get', + new=new_event_get): + with mock.patch.object(app_module.pygame.display, 'flip'): + app.run() + + assert app._unblank.call_count == 2 + assert app._blank.call_count == 2 + + def test_run_handling_click_to_prev_event(self): + app = self._mocked_app() + app._internal_events = set([EVENT_CLICK_TO_PREV_CARD]) + + def clock_tick(*args, **kwargs): + app.quit() + + app._clock.tick = mock.Mock(side_effect=clock_tick) + app._get_events = mock.Mock() + + with mock.patch.object(app_module.sys, 'exit'): + with mock.patch.object(app_module.pygame.display, 'flip'): + app.run() + + app._transition_cards.assert_called_with( + direction=-1, force=True + ) + + def test_run_handling_click_to_next_event(self): + app = self._mocked_app() + app._internal_events = set([EVENT_CLICK_TO_PREV_CARD]) + + def clock_tick(*args, **kwargs): + app.quit() + + app._clock.tick = mock.Mock(side_effect=clock_tick) + app._get_events = mock.Mock() + + with mock.patch.object(app_module.sys, 'exit'): + with mock.patch.object(app_module.pygame.display, 'flip'): + app.run() + + app._transition_cards.assert_called_with( + direction=-1, force=True + ) + + def test_quit(self): + app = self._mocked_app() + app.quit() + assert app._should_quit is True diff --git a/tests/test_clock_card.py b/tests/test_clock_card.py new file mode 100644 index 0000000..a0662bd --- /dev/null +++ b/tests/test_clock_card.py @@ -0,0 +1,229 @@ +# -*- coding: utf-8 -*- + +import datetime + +import mock +import pygame + +from pie_time import application as app_module +from pie_time.application import PieTime +from pie_time.cards import ClockCard + + +class Test_ClockCard(object): + def _dummy_card(self, **settings): + app = PieTime(None, screen_size=(320, 240)) + app.path_for_resource = mock.Mock( + side_effect=lambda resource: resource + ) + card = ClockCard() + card.set_app(app) + card.set_settings(settings) + + return card + + def test_initialize(self): + with mock.patch.object(app_module.pygame.font, 'Font', + spec=pygame.font.Font): + card = self._dummy_card() + card.initialize() + assert card._time_font is not None + assert card._date_font is not None + + def test_render_time(self): + with mock.patch.object(app_module.pygame.font, 'Font', + spec=pygame.font.Font): + card = self._dummy_card() + card.initialize() + + now = datetime.datetime.now().replace(second=0) + card._render_time(now) + card._time_font.render.assert_called_with( + now.strftime(card.TIME_FORMAT), True, card.GREEN + ) + + now = datetime.datetime.now().replace(second=1) + card._render_time(now) + card._time_font.render.assert_called_with( + now.strftime(card.TIME_FORMAT).replace(':', ' '), True, + card.GREEN + ) + + def test_render_time_override_format(self): + with mock.patch.object(app_module.pygame.font, 'Font', + spec=pygame.font.Font): + time_format = '%H:%M' + card = self._dummy_card(time_format=time_format) + card.initialize() + + now = datetime.datetime.now().replace(second=0) + card._render_time(now) + card._time_font.render.assert_called_with( + now.strftime(time_format), True, card.GREEN + ) + + def test_render_time_override_color(self): + with mock.patch.object(app_module.pygame.font, 'Font', + spec=pygame.font.Font): + time_color = (255, 255, 255) + card = self._dummy_card(time_color=time_color) + card.initialize() + + now = datetime.datetime.now().replace(second=0) + card._render_time(now) + card._time_font.render.assert_called_with( + now.strftime(card.TIME_FORMAT), True, (255, 255, 255) + ) + + def test_render_time_override_blink(self): + with mock.patch.object(app_module.pygame.font, 'Font', + spec=pygame.font.Font): + card = self._dummy_card(time_blink=False) + card.initialize() + + now = datetime.datetime.now().replace(second=1) + card._render_time(now) + card._time_font.render.assert_called_with( + now.strftime(card.TIME_FORMAT), True, card.GREEN + ) + + def test_render_date(self): + with mock.patch.object(app_module.pygame.font, 'Font', + spec=pygame.font.Font): + card = self._dummy_card() + card.initialize() + + now = datetime.datetime.now() + card._render_date(now) + card._date_font.render.assert_called_with( + now.strftime(card.DATE_FORMAT), True, card.GREEN + ) + + def test_render_date_override_format(self): + with mock.patch.object(app_module.pygame.font, 'Font', + spec=pygame.font.Font): + date_format = '%Y-%M-%D' + card = self._dummy_card(date_format=date_format) + card.initialize() + + now = datetime.datetime.now().replace(second=0) + card._render_date(now) + card._date_font.render.assert_called_with( + now.strftime(date_format), True, card.GREEN + ) + + def test_render_date_override_color(self): + with mock.patch.object(app_module.pygame.font, 'Font', + spec=pygame.font.Font): + date_color = (255, 255, 255) + card = self._dummy_card(date_color=date_color) + card.initialize() + + now = datetime.datetime.now().replace(second=0) + card._render_date(now) + card._date_font.render.assert_called_with( + now.strftime(card.DATE_FORMAT), True, (255, 255, 255) + ) + + def test_update_now(self): + now = datetime.datetime.now() + current_delta = 0 + + fake_datetime = mock.Mock(spec=datetime.datetime) + + def fake_datetime_now(*args, **kwargs): + return now + datetime.timedelta(seconds=current_delta) + + fake_datetime.now = mock.Mock(side_effect=fake_datetime_now) + + with mock.patch.object(app_module.datetime, 'datetime', + new=fake_datetime): + with mock.patch.object(app_module.pygame.font, 'Font', + spec=pygame.font.Font): + card = self._dummy_card() + card.initialize() + + card._app = mock.Mock(spec=PieTime) + card._app._clock = mock.Mock(spec=pygame.time.Clock) + card._app._clock.get_time = mock.Mock( + side_effect=lambda: current_delta + ) + + assert card._update_now() is True + assert card._now == now + assert card._current_interval == 0 + + current_delta = 500 + assert card._update_now() is False + assert card._now == now + assert card._current_interval == current_delta + + current_delta = 530 + assert card._update_now() is True + assert card._now > now + assert card._current_interval == 30 + + def test_show(self): + card = self._dummy_card() + card._now = datetime.datetime.now() + + card.show() + assert card._now is None + + def test_tick_redraw(self): + now = datetime.datetime.now() + + with mock.patch.object(app_module.pygame.font, 'Font', + spec=pygame.font.Font): + card = self._dummy_card() + card.initialize() + + card._now = now + card._surface = mock.Mock(spec=pygame.surface.Surface) + card._update_now = mock.Mock(return_value=True) + + time_surface = mock.Mock(spec=pygame.surface.Surface) + time_surface.get_size = mock.Mock(return_value=(120, 80)) + card._render_time = mock.Mock(return_value=time_surface) + + date_surface = mock.Mock(spec=pygame.surface.Surface) + date_surface.get_size = mock.Mock(return_value=(200, 60)) + card._render_date = mock.Mock(return_value=date_surface) + + card.tick() + assert card._update_now.called + card._render_time.assert_called_with(now) + card._render_date.assert_called_with(now) + + assert time_surface.get_size.called + assert date_surface.get_size.called + + card.surface.fill.assert_called_with(card.background_color) + card.surface.blit.assert_any_call( + time_surface, (100, 50, 120, 80) + ) + card.surface.blit.assert_any_call( + date_surface, (60, 130, 200, 60) + ) + + def test_tick_dont_redraw(self): + with mock.patch.object(app_module.pygame.font, 'Font', + spec=pygame.font.Font): + card = self._dummy_card() + card.initialize() + + card._surface = mock.Mock(spec=pygame.surface.Surface) + card._update_now = mock.Mock(return_value=False) + + card._render_time = mock.Mock() + card._render_date = mock.Mock() + + card.tick() + + assert card._update_now.called + + assert card._render_time.called is False + assert card._render_date.called is False + + assert card.surface.fill.called is False + assert card.surface.blit.called is False diff --git a/tests/test_picture_card.py b/tests/test_picture_card.py new file mode 100644 index 0000000..c11b016 --- /dev/null +++ b/tests/test_picture_card.py @@ -0,0 +1,266 @@ +# -*- coding: utf-8 -*- + +import cStringIO + +import mock +import pygame +import requests + +from pie_time.application import PieTime +from pie_time.cards import picture as card_module +from pie_time.cards import PictureCard + + +class Test_PictureCard(object): + def _dummy_card(self, **settings): + app = PieTime(None, screen_size=(320, 240)) + app.screen = mock.Mock(spec=pygame.surface.Surface) + app._logger = mock.Mock() + + app.path_for_resource = mock.Mock( + side_effect=lambda resource: resource + ) + + card = PictureCard() + card.set_app(app) + card.set_settings(settings) + + return card + + def _dummy_initialized_card(self, **settings): + card = self._dummy_card(**settings) + card._load_picture = mock.Mock( + side_effect=lambda x: mock.Mock(spec=pygame.surface.Surface) + ) + + card.initialize() + return card + + def test_initialize(self): + urls = ['spam', 'eggs'] + + card = self._dummy_card(urls=urls) + card._load_picture = mock.Mock() + + card.initialize() + assert len(card._pictures) == len(urls) + assert card._current_picture_idx is None + + assert card._load_picture.call_count == len(urls) + card._load_picture.assert_any_call(urls[0]) + card._load_picture.assert_any_call(urls[1]) + + def test_load_picture_file(self): + fake_image = mock.Mock(spec=pygame.surface.Surface) + + with mock.patch.object(card_module.pygame.image, 'load', + return_value=fake_image): + card = self._dummy_card() + result = card._load_picture('file:///spam') + assert result == fake_image + + card_module.pygame.image.load.assert_called_with('/spam') + + def test_load_picture_file_load_error(self): + with mock.patch.object(card_module.pygame.image, 'load', + side_effect=RuntimeError('ERROR')): + card = self._dummy_card() + result = card._load_picture('file:///spam') + assert result is None + + def test_load_picture_net(self): + fake_image = mock.Mock(spec=pygame.surface.Surface) + + fake_response = mock.Mock(spec=requests.Response) + fake_response.status_code = 200 + fake_response.headers = {'Content-Type': ''} + fake_response.content = 'HERE IMAGE DATA BE' + + fake_stringio = mock.Mock(spec=cStringIO.StringIO) + + with mock.patch.object(card_module.pygame.image, 'load', + return_value=fake_image): + with mock.patch.object(card_module.requests, 'get', + return_value=fake_response): + with mock.patch.object(card_module.cStringIO, 'StringIO', + return_value=fake_stringio): + url = 'http://spam.com/eggs' + card = self._dummy_card() + + result = card._load_picture(url) + assert result == fake_image + + card_module.requests.get.assert_called_with(url) + + card_module.cStringIO.StringIO.assert_called_with( + fake_response.content + ) + + card_module.pygame.image.load.assert_called_with( + fake_stringio, 'picture.' + ) + + def test_load_picture_net_requests_error(self): + def _get(*args, **kwargs): + raise RuntimeError('ERROR') + + new_get = mock.Mock(side_effect=_get) + + with mock.patch.object(card_module.requests, 'get', + side_effect=RuntimeError('TODO')): + url = 'http://spam.com/eggs' + card = self._dummy_card() + + result = card._load_picture(url) + assert result is None + + def test_load_picture_net_bad_response(self): + fake_response = mock.Mock(spec=requests.Response) + fake_response.status_code = 404 + + with mock.patch.object(card_module.requests, 'get', + return_value=fake_response): + url = 'http://spam.com/eggs' + card = self._dummy_card() + + result = card._load_picture(url) + assert result is None + + def test_load_picture_net_load_error(self): + fake_response = mock.Mock(spec=requests.Response) + fake_response.status_code = 200 + fake_response.headers = {'Content-Type': ''} + fake_response.content = 'HERE IMAGE DATA BE' + + with mock.patch.object(card_module.pygame.image, 'load', + side_effect=RuntimeError('ERROR')): + with mock.patch.object(card_module.requests, 'get', + return_value=fake_response): + url = 'http://spam.com/eggs' + card = self._dummy_card() + + result = card._load_picture(url) + assert result is None + + def test_load_picture_convert(self): + fake_image = mock.Mock(spec=pygame.surface.Surface) + fake_image.convert = mock.Mock(return_value=fake_image) + + with mock.patch.object(card_module.pygame.image, 'load', + return_value=fake_image): + card = self._dummy_card() + result = card._load_picture('file:///spam.jpg') + assert result == fake_image + + fake_image.convert.assert_called_with(card._app.screen) + + def test_load_picture_convert_alpha(self): + fake_image = mock.Mock(spec=pygame.surface.Surface) + fake_image.convert_alpha = mock.Mock(return_value=fake_image) + + with mock.patch.object(card_module.pygame.image, 'load', + return_value=fake_image): + card = self._dummy_card() + result = card._load_picture('file:///spam.png') + assert result == fake_image + + fake_image.convert_alpha.assert_called_with(card._app.screen) + + def test_show_no_pictures(self): + card = self._dummy_initialized_card(urls=[]) + card.show() + assert card._current_picture_idx is None + assert card._should_redraw is True + + def test_show_one_picture(self): + card = self._dummy_initialized_card(urls=['http://spam.com/eggs.png']) + + card.show() + assert card._current_picture_idx == 0 + assert card._should_redraw is True + + card.show() + assert card._current_picture_idx == 0 + assert card._should_redraw is True + + def test_show_many_pictures(self): + card = self._dummy_initialized_card( + urls=[ + 'http://spam.com/eggs.png', 'http://spam.com/spam.png', + 'http://spam.com/spameggs.png' + ] + ) + + card.show() + assert card._current_picture_idx == 0 + assert card._should_redraw is True + + card.show() + assert card._current_picture_idx == 1 + assert card._should_redraw is True + + card.show() + assert card._current_picture_idx == 2 + assert card._should_redraw is True + + card.show() + assert card._current_picture_idx == 0 + assert card._should_redraw is True + + def test_tick_no_pictures(self): + card = self._dummy_initialized_card(urls=[]) + card._surface = mock.Mock(spec=pygame.surface.Surface) + card.show() + + card.tick() + assert card._should_redraw is False + + card.surface.fill.assert_called_with(card.background_color) + + def test_tick_with_pictures(self): + card = self._dummy_initialized_card( + urls=['http://spam.com/eggs.png', 'http://spam.com/eggs.png'] + ) + + card._surface = mock.Mock(spec=pygame.surface.Surface) + + card._pictures[0].get_size = mock.Mock(return_value=(320, 240)) + card._pictures[0].get_rect = mock.Mock( + return_value=(0, 0, 320, 240) + ) + + card._pictures[1].get_size = mock.Mock(return_value=(240, 180)) + card._pictures[1].get_rect = mock.Mock( + return_value=(0, 0, 240, 180) + ) + + card.show() + card.tick() + assert card._should_redraw is False + card.surface.fill.assert_called_with(card.background_color) + card.surface.blit.assert_called_with( + card._pictures[0], (0, 0, 320, 240) + ) + + card.show() + card.tick() + assert card._should_redraw is False + card.surface.fill.assert_called_with(card.background_color) + card.surface.blit.assert_called_with( + card._pictures[1], (40, 30, 240, 180) + ) + + def test_tick_dont_redraw(self): + card = self._dummy_initialized_card( + urls=['http://spam.com/eggs.png', 'http://spam.com/eggs.png'] + ) + + card._surface = mock.Mock(spec=pygame.surface.Surface) + card.show() + card._should_redraw = False + + card.tick() + assert card._should_redraw is False + + assert card.surface.fill.called is False + assert card.surface.blit.called is False diff --git a/tests/test_weather_card.py b/tests/test_weather_card.py new file mode 100644 index 0000000..b2b286b --- /dev/null +++ b/tests/test_weather_card.py @@ -0,0 +1,697 @@ +# -*- coding: utf-8 -*- + +import threading + +import mock +import pygame +import requests + +from pie_time.application import PieTime +from pie_time.cards import weather as card_module + + +class Test_WeatherCard(object): + def _dummy_card(self, city='Wroclaw,PL', api_key='API key', **settings): + app = PieTime(None, screen_size=(320, 240)) + app._logger = mock.Mock() + app.path_for_resource = mock.Mock( + side_effect=lambda resource: resource + ) + card = card_module.WeatherCard() + card.set_app(app) + + if city: + settings['city'] = city + + if api_key: + settings['api_key'] = api_key + + card.set_settings(settings) + + return card + + def _ok_payload(self): + return { + "base": "cmc stations", + "clouds": { + "all": 20 + }, + "cod": 200, + "coord": { + "lat": 51.1, + "lon": 17.03 + }, + "dt": 1413815400, + "id": 3081368, + "main": { + "humidity": 59, + "pressure": 1013, + "temp": 17, + "temp_max": 17, + "temp_min": 17 + }, + "name": "Wroclaw", + "sys": { + "country": "PL", + "id": 5375, + "message": 0.1316, + "sunrise": 1413782666, + "sunset": 1413820124, + "type": 1 + }, + "weather": [ + { + "description": "few clouds", + "icon": "02d", + "id": 801, + "main": "Clouds" + } + ], + "wind": { + "deg": 280, + "speed": 6.2 + } + } + + def test_initialize_no_city(self): + card = self._dummy_card(city=None) + + try: + card.initialize() + except Exception as exc: + assert isinstance(exc, AssertionError) + assert exc.args[0] == 'Configuration error: missing city' + else: + assert False, 'Nothing was raised :(' + + def test_initialize_no_api_key(self): + card = self._dummy_card(api_key=None) + + try: + card.initialize() + except Exception as exc: + assert isinstance(exc, AssertionError) + assert exc.args[0] == 'Configuration error: missing API key' + else: + assert False, 'Nothing was raised :(' + + def test_initialize(self): + with mock.patch.object(card_module.pygame.font, 'Font', + spec=pygame.font.Font): + card = self._dummy_card() + card._refresh_conditions = mock.Mock() + + card.initialize() + + assert card._text_font is not None + assert card._temp_font is not None + assert card._icon_font is not None + assert card._timer is None + assert card._current_conditions is None + assert card._refresh_conditions.called + + def test_refresh_conditions_requests_error(self): + fake_timer = mock.Mock(spec=threading.Timer) + fake_timer.start = mock.Mock() + + with mock.patch.object(card_module.pygame.font, 'Font', + spec=pygame.font.Font): + with mock.patch.object(card_module.requests, 'get', + side_effect=RuntimeError('TODO')): + with mock.patch.object(card_module, 'Timer', + return_value=fake_timer): + card = self._dummy_card() + card.initialize(refresh=False) + card._refresh_conditions() + + assert card_module.requests.get.called + assert card._current_conditions is None + + assert card._timer is not None + card_module.Timer.assert_called_with( + card.REFRESH_INTERVAL, card._refresh_conditions + ) + assert card._timer.start.called + + def test_refresh_conditions_bad_status_code(self): + fake_response = mock.Mock(spec=requests.Response) + fake_response.status_code = 404 + + fake_timer = mock.Mock(spec=threading.Timer) + fake_timer.start = mock.Mock() + + with mock.patch.object(card_module.pygame.font, 'Font', + spec=pygame.font.Font): + with mock.patch.object(card_module.requests, 'get', + return_value=fake_response): + with mock.patch.object(card_module, 'Timer', + return_value=fake_timer): + card = self._dummy_card() + card.initialize(refresh=False) + card._refresh_conditions() + + assert card_module.requests.get.called + assert card._current_conditions is None + + assert card._timer is not None + card_module.Timer.assert_called_with( + card.REFRESH_INTERVAL, card._refresh_conditions + ) + assert card._timer.start.called + + def test_refresh_conditions_missing_weather_object(self): + payload = self._ok_payload() + payload['weather'] = [] + + fake_response = mock.Mock(spec=requests.Response) + fake_response.json = mock.Mock(return_value=payload) + fake_response.status_code = 200 + + fake_timer = mock.Mock(spec=threading.Timer) + fake_timer.start = mock.Mock() + + with mock.patch.object(card_module.pygame.font, 'Font', + spec=pygame.font.Font): + with mock.patch.object(card_module.requests, 'get', + return_value=fake_response): + with mock.patch.object(card_module, 'Timer', + return_value=fake_timer): + card = self._dummy_card() + card.initialize(refresh=False) + card._refresh_conditions() + + assert card_module.requests.get.called + assert card._current_conditions is None + + assert card._timer is not None + card_module.Timer.assert_called_with( + card.REFRESH_INTERVAL, card._refresh_conditions + ) + assert card._timer.start.called + + def test_refresh_conditions_missing_conditions(self): + payload = self._ok_payload() + payload['weather'][0].pop('main') + + fake_response = mock.Mock(spec=requests.Response) + fake_response.json = mock.Mock(return_value=payload) + fake_response.status_code = 200 + + fake_timer = mock.Mock(spec=threading.Timer) + fake_timer.start = mock.Mock() + + with mock.patch.object(card_module.pygame.font, 'Font', + spec=pygame.font.Font): + with mock.patch.object(card_module.requests, 'get', + return_value=fake_response): + with mock.patch.object(card_module, 'Timer', + return_value=fake_timer): + card = self._dummy_card() + card.initialize(refresh=False) + card._refresh_conditions() + + assert card_module.requests.get.called + assert card._current_conditions is None + + assert card._timer is not None + card_module.Timer.assert_called_with( + card.REFRESH_INTERVAL, card._refresh_conditions + ) + assert card._timer.start.called + + def test_refresh_conditions_missing_temp(self): + payload = self._ok_payload() + payload['main'].pop('temp') + + fake_response = mock.Mock(spec=requests.Response) + fake_response.json = mock.Mock(return_value=payload) + fake_response.status_code = 200 + + fake_timer = mock.Mock(spec=threading.Timer) + fake_timer.start = mock.Mock() + + with mock.patch.object(card_module.pygame.font, 'Font', + spec=pygame.font.Font): + with mock.patch.object(card_module.requests, 'get', + return_value=fake_response): + with mock.patch.object(card_module, 'Timer', + return_value=fake_timer): + card = self._dummy_card() + card.initialize(refresh=False) + card._refresh_conditions() + + assert card_module.requests.get.called + assert card._current_conditions is None + + assert card._timer is not None + card_module.Timer.assert_called_with( + card.REFRESH_INTERVAL, card._refresh_conditions + ) + assert card._timer.start.called + + def test_refresh_conditions(self): + payload = self._ok_payload() + + fake_response = mock.Mock(spec=requests.Response) + fake_response.json = mock.Mock(return_value=payload) + fake_response.status_code = 200 + + fake_timer = mock.Mock(spec=threading.Timer) + fake_timer.start = mock.Mock() + + with mock.patch.object(card_module.pygame.font, 'Font', + spec=pygame.font.Font): + with mock.patch.object(card_module.requests, 'get', + return_value=fake_response): + with mock.patch.object(card_module, 'Timer', + return_value=fake_timer): + card = self._dummy_card() + card.initialize(refresh=False) + card._refresh_conditions() + + assert card_module.requests.get.called + assert card._current_conditions == { + 'conditions': payload['weather'][0]['main'], + 'icon': payload['weather'][0]['icon'], + 'temperature': payload['main']['temp'], + } + + assert card._timer is not None + card_module.Timer.assert_called_with( + card.REFRESH_INTERVAL, card._refresh_conditions + ) + assert card._timer.start.called + + def test_refresh_conditions_no_icon(self): + payload = self._ok_payload() + payload['weather'][0].pop('icon') + + fake_response = mock.Mock(spec=requests.Response) + fake_response.json = mock.Mock(return_value=payload) + fake_response.status_code = 200 + + fake_timer = mock.Mock(spec=threading.Timer) + fake_timer.start = mock.Mock() + + with mock.patch.object(card_module.pygame.font, 'Font', + spec=pygame.font.Font): + with mock.patch.object(card_module.requests, 'get', + return_value=fake_response): + with mock.patch.object(card_module, 'Timer', + return_value=fake_timer): + card = self._dummy_card() + card.initialize(refresh=False) + card._refresh_conditions() + + assert card_module.requests.get.called + assert card._current_conditions == { + 'conditions': payload['weather'][0]['main'], + 'icon': None, + 'temperature': payload['main']['temp'], + } + + assert card._timer is not None + card_module.Timer.assert_called_with( + card.REFRESH_INTERVAL, card._refresh_conditions + ) + assert card._timer.start.called + + def test_render_city(self): + card = self._dummy_card() + + with mock.patch.object(card_module.pygame.font, 'Font', + spec=pygame.font.Font): + card.initialize(refresh=False) + + card._text_font.render = mock.Mock( + return_value=mock.Mock(spec=pygame.surface.Surface) + ) + + surface = card._render_city() + + card._text_font.render.assert_called_with( + card._settings['city'], True, card.WHITE + ) + assert isinstance(surface, pygame.surface.Surface) + + def test_render_city_override_color(self): + card = self._dummy_card(city_color=(255, 0, 0)) + + with mock.patch.object(card_module.pygame.font, 'Font', + spec=pygame.font.Font): + card.initialize(refresh=False) + + card._text_font.render = mock.Mock( + return_value=mock.Mock(spec=pygame.surface.Surface) + ) + + surface = card._render_city() + + card._text_font.render.assert_called_with( + card._settings['city'], True, (255, 0, 0) + ) + assert isinstance(surface, pygame.surface.Surface) + + def test_render_conditions(self): + card = self._dummy_card() + + with mock.patch.object(card_module.pygame.font, 'Font', + spec=pygame.font.Font): + card.initialize(refresh=False) + card._current_conditions = { + 'conditions': 'clouds' + } + + card._text_font.render = mock.Mock( + return_value=mock.Mock(spec=pygame.surface.Surface) + ) + + surface = card._render_conditions() + + card._text_font.render.assert_called_with( + 'Clouds', True, card.WHITE + ) + assert isinstance(surface, pygame.surface.Surface) + + def test_render_conditions_override_color(self): + card = self._dummy_card(conditions_color=(255, 0, 0)) + + with mock.patch.object(card_module.pygame.font, 'Font', + spec=pygame.font.Font): + card.initialize(refresh=False) + card._current_conditions = { + 'conditions': 'clouds' + } + + card._text_font.render = mock.Mock( + return_value=mock.Mock(spec=pygame.surface.Surface) + ) + + surface = card._render_conditions() + + card._text_font.render.assert_called_with( + 'Clouds', True, (255, 0, 0) + ) + assert isinstance(surface, pygame.surface.Surface) + + def test_render_icon(self): + card = self._dummy_card() + + with mock.patch.object(card_module.pygame.font, 'Font', + spec=pygame.font.Font): + card.initialize(refresh=False) + icon_code = '01d' + card._current_conditions = {'icon': icon_code} + + card._text_font.render = mock.Mock( + return_value=mock.Mock(spec=pygame.surface.Surface) + ) + + surface = card._render_icon() + + card._icon_font.render.assert_called_with( + card.WEATHER_CODE_TO_ICON[icon_code], True, card.WHITE + ) + assert isinstance(surface, pygame.surface.Surface) + + def test_render_icon_override_color(self): + card = self._dummy_card(icon_color=(255, 0, 0)) + + with mock.patch.object(card_module.pygame.font, 'Font', + spec=pygame.font.Font): + card.initialize(refresh=False) + icon_code = '01d' + card._current_conditions = {'icon': icon_code} + + card._text_font.render = mock.Mock( + return_value=mock.Mock(spec=pygame.surface.Surface) + ) + + surface = card._render_icon() + + card._icon_font.render.assert_called_with( + card.WEATHER_CODE_TO_ICON[icon_code], True, (255, 0, 0) + ) + assert isinstance(surface, pygame.surface.Surface) + + def test_render_icon_no_icon(self): + card = self._dummy_card() + + with mock.patch.object(card_module.pygame.font, 'Font', + spec=pygame.font.Font): + card.initialize(refresh=False) + icon_code = None + card._current_conditions = {'icon': icon_code} + + card._text_font.render = mock.Mock( + return_value=mock.Mock(spec=pygame.surface.Surface) + ) + + surface = card._render_icon() + + assert card._icon_font.render.called is False + assert surface is None + + def test_render_icon_unknown_icon(self): + card = self._dummy_card() + + with mock.patch.object(card_module.pygame.font, 'Font', + spec=pygame.font.Font): + card.initialize(refresh=False) + icon_code = 'spam' + card._current_conditions = {'icon': icon_code} + + card._text_font.render = mock.Mock( + return_value=mock.Mock(spec=pygame.surface.Surface) + ) + + surface = card._render_icon() + + assert card._icon_font.render.called is False + assert surface is None + + def test_render_temperature(self): + card = self._dummy_card() + + with mock.patch.object(card_module.pygame.font, 'Font', + spec=pygame.font.Font): + card.initialize(refresh=False) + card._current_conditions = { + 'temperature': 17 + } + + card._text_font.render = mock.Mock( + return_value=mock.Mock(spec=pygame.surface.Surface) + ) + + surface = card._render_temperature() + + card._text_font.render.assert_called_with( + u'17°', True, card.WHITE + ) + assert isinstance(surface, pygame.surface.Surface) + + def test_render_temperature_override_color(self): + card = self._dummy_card(temperature_color=(255, 0, 0)) + + with mock.patch.object(card_module.pygame.font, 'Font', + spec=pygame.font.Font): + card.initialize(refresh=False) + card._current_conditions = { + 'temperature': 17 + } + + card._text_font.render = mock.Mock( + return_value=mock.Mock(spec=pygame.surface.Surface) + ) + + surface = card._render_temperature() + + card._text_font.render.assert_called_with( + u'17°', True, (255, 0, 0) + ) + assert isinstance(surface, pygame.surface.Surface) + + def test_quit(self): + card = self._dummy_card() + card._timer = None + card.quit() + + card = self._dummy_card() + card._timer = mock.Mock(spec=threading.Timer) + card._timer.cancel = mock.Mock() + + card.quit() + assert card._timer.cancel.called + + def test_tick_redraw(self): + card = self._dummy_card() + + with mock.patch.object(card_module.pygame.font, 'Font', + spec=pygame.font.Font): + card.initialize(refresh=False) + card._current_conditions = { + 'conditions': 'Clouds', + 'icon': '01d', + 'temperature': 17 + } + + card._surface = mock.Mock(spec=pygame.surface.Surface) + + city_surface = mock.Mock(spec=pygame.surface.Surface) + city_surface.get_size = mock.Mock(return_value=(120, 40)) + card._render_city = mock.Mock(return_value=city_surface) + + conditions_surface = mock.Mock(spec=pygame.surface.Surface) + conditions_surface.get_size = mock.Mock(return_value=(200, 40)) + card._render_conditions = mock.Mock( + return_value=conditions_surface + ) + + icon_surface = mock.Mock(spec=pygame.surface.Surface) + icon_surface.get_size = mock.Mock(return_value=(128, 128)) + card._render_icon = mock.Mock(return_value=icon_surface) + + temperature_surface = mock.Mock(spec=pygame.surface.Surface) + temperature_surface.get_size = mock.Mock(return_value=(100, 82)) + card._render_temperature = mock.Mock( + return_value=temperature_surface + ) + + card.tick() + + card.surface.blit.assert_any_call( + city_surface, (100, 0, 120, 40) + ) + + card.surface.blit.assert_any_call( + conditions_surface, (60, 200, 200, 40) + ) + + card.surface.blit.assert_any_call( + icon_surface, (34, 56, 128, 128) + ) + + card.surface.blit.assert_any_call( + temperature_surface, (186, 79, 100, 82) + ) + + assert card._should_redraw is False + + def test_tick_dont_redraw(self): + card = self._dummy_card() + + with mock.patch.object(card_module.pygame.font, 'Font', + spec=pygame.font.Font): + card.initialize(refresh=False) + card._should_redraw = False + + card._surface = mock.Mock(spec=pygame.surface.Surface) + + city_surface = mock.Mock(spec=pygame.surface.Surface) + city_surface.get_size = mock.Mock(return_value=(120, 40)) + card._render_city = mock.Mock(return_value=city_surface) + + conditions_surface = mock.Mock(spec=pygame.surface.Surface) + conditions_surface.get_size = mock.Mock(return_value=(200, 40)) + card._render_conditions = mock.Mock( + return_value=conditions_surface + ) + + icon_surface = mock.Mock(spec=pygame.surface.Surface) + icon_surface.get_size = mock.Mock(return_value=(128, 128)) + card._render_icon = mock.Mock(return_value=icon_surface) + + temperature_surface = mock.Mock(spec=pygame.surface.Surface) + temperature_surface.get_size = mock.Mock(return_value=(100, 82)) + card._render_temperature = mock.Mock( + return_value=temperature_surface + ) + + card.tick() + + assert card._render_city.called is False + assert card._render_conditions.called is False + assert card._render_icon.called is False + assert card._render_temperature.called is False + assert card.surface.blit.called is False + + assert card._should_redraw is False + + def test_tick_without_icon(self): + card = self._dummy_card() + + with mock.patch.object(card_module.pygame.font, 'Font', + spec=pygame.font.Font): + card.initialize(refresh=False) + card._current_conditions = { + 'conditions': 'Clouds', + 'icon': '01d', + 'temperature': 17 + } + + card._surface = mock.Mock(spec=pygame.surface.Surface) + + city_surface = mock.Mock(spec=pygame.surface.Surface) + city_surface.get_size = mock.Mock(return_value=(120, 40)) + card._render_city = mock.Mock(return_value=city_surface) + + conditions_surface = mock.Mock(spec=pygame.surface.Surface) + conditions_surface.get_size = mock.Mock(return_value=(200, 40)) + card._render_conditions = mock.Mock( + return_value=conditions_surface + ) + + card._render_icon = mock.Mock(return_value=None) + + temperature_surface = mock.Mock(spec=pygame.surface.Surface) + temperature_surface.get_size = mock.Mock(return_value=(100, 82)) + card._render_temperature = mock.Mock( + return_value=temperature_surface + ) + + card.tick() + + card.surface.blit.assert_any_call( + city_surface, (100, 0, 120, 40) + ) + + card.surface.blit.assert_any_call( + conditions_surface, (60, 200, 200, 40) + ) + + card.surface.blit.assert_any_call( + temperature_surface, (110, 79, 100, 82) + ) + + assert card._should_redraw is False + + def test_tick_without_conditions(self): + card = self._dummy_card() + + with mock.patch.object(card_module.pygame.font, 'Font', + spec=pygame.font.Font): + card.initialize(refresh=False) + + card._surface = mock.Mock(spec=pygame.surface.Surface) + + city_surface = mock.Mock(spec=pygame.surface.Surface) + city_surface.get_size = mock.Mock(return_value=(120, 40)) + card._render_city = mock.Mock(return_value=city_surface) + + card._render_conditions = mock.Mock() + card._render_icon = mock.Mock() + card._render_temperature = mock.Mock() + + card.tick() + + assert card.surface.blit.call_count == 1 + card.surface.blit.assert_called_with( + city_surface, (100, 0, 120, 40) + ) + + assert card._render_conditions.called is False + assert card._render_icon.called is False + assert card._render_temperature.called is False + + assert card._should_redraw is False