1
0
mirror of https://github.com/gryf/pygtktalog.git synced 2025-12-17 11:30:19 +01:00

Added tox configuration

This commit is contained in:
2016-08-21 16:25:32 +02:00
parent bb5928a9f6
commit 22d7e62357
8 changed files with 75 additions and 323 deletions

6
.gitignore vendored
View File

@@ -1,2 +1,8 @@
__pycache__/ __pycache__/
*.py[cod] *.py[cod]
.coverage
.tox
tags
MANIFEST
.cache
pygtktalog.egg-info

View File

@@ -6,12 +6,11 @@
Created: 2009-05-05 Created: 2009-05-05
""" """
__version__ = "1.9.0" __version__ = "2.0.0"
__appname__ = "pyGTKtalog" __appname__ = "pyGTKtalog"
__copyright__ = u"\u00A9 Roman 'gryf' Dobosz" __copyright__ = u"\u00A9 Roman 'gryf' Dobosz"
__summary__ = "%s is simple tool for managing file collections." % __appname__ __summary__ = "%s is simple tool for managing file collections." % __appname__
__web__ = "http://bitbucket.org/gryf" __web__ = "http://github.com/gryf/pygtktalog"
__logo_img__ = "views/pixmaps/Giant Worms.png"
import os import os
import sys import sys
@@ -19,15 +18,10 @@ import locale
import gettext import gettext
import __builtin__ import __builtin__
import gtk.glade
from pygtktalog.logger import get_logger from pygtktalog.logger import get_logger
__all__ = ['controllers', __all__ = ['EXIF',
'models',
'views',
'EXIF',
'dbcommon', 'dbcommon',
'dbobjects', 'dbobjects',
'dialogs', 'dialogs',
@@ -48,12 +42,12 @@ except locale.Error:
# unknown locale string, fallback to C # unknown locale string, fallback to C
locale.setlocale(locale.LC_ALL, 'C') locale.setlocale(locale.LC_ALL, 'C')
for module in gtk.glade, gettext: # for module in gtk.glade, gettext:
if os.path.exists(LOCALE_PATH): # if os.path.exists(LOCALE_PATH):
module.bindtextdomain(GETTEXT_DOMAIN, LOCALE_PATH) # module.bindtextdomain(GETTEXT_DOMAIN, LOCALE_PATH)
else: # else:
module.bindtextdomain(GETTEXT_DOMAIN) # module.bindtextdomain(GETTEXT_DOMAIN)
module.textdomain(GETTEXT_DOMAIN) # module.textdomain(GETTEXT_DOMAIN)
# register the gettext function for the whole interpreter as "_" # register the gettext function for the whole interpreter as "_"
__builtin__._ = gettext.gettext __builtin__._ = gettext.gettext

View File

@@ -1,231 +0,0 @@
"""
Project: pyGTKtalog
Description: Simple dialogs for interact with user
Type: helper
Author: Roman 'gryf' Dobosz, gryf73@gmail.com
Created: 2009-05-12
"""
import os
import gtk
import pygtktalog
class Dialog(object):
"""
Show simple dialog for questions
Returns: Bool - True, if "OK" button pressed, False otherwise.
"""
def __init__(self, dialog_type, message, secondary_msg="", title=""):
"""
Initialize some defaults
"""
self.dialog = None
self.buttons = gtk.BUTTONS_OK
self.ok_default = False
self.message = message
self.secondary_msg = secondary_msg
self.type = dialog_type
self.title = title
def run(self):
"""Show the dialog"""
if self.dialog is None:
self._create_dialog()
# Change default/focus from cancel/no to ok/yes. Suitable only for
# Question dialog.
# Ofcourse, if something changes in the future, this could break
# things.
if self.ok_default:
# this is tricky: Ok/Yes buttons appears as first on the list, but
# they are visibile in oposite order. This could be a bug.
button = self.dialog.get_action_area().get_children()[0]
button.grab_default()
retval = self.dialog.run()
self.dialog.destroy()
if retval == gtk.RESPONSE_OK or retval == gtk.RESPONSE_YES:
return True
return False
def _create_dialog(self):
"""Create MessageDialog widgt"""
if self.type == gtk.MESSAGE_QUESTION and \
self.buttons not in (gtk.BUTTONS_YES_NO, gtk.BUTTONS_OK_CANCEL):
self.buttons = gtk.BUTTONS_YES_NO
self.dialog = gtk.MessageDialog(buttons=self.buttons, type=self.type,
message_format=self.message)
self.dialog.format_secondary_text(self.secondary_msg)
self.dialog.set_title(self.title)
class ChooseFile(object):
"""
Common file chooser
"""
URI = None
BUTTON_PAIRS = {'cancel': (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL),
'ok': (gtk.STOCK_OK, gtk.RESPONSE_APPLY),
'save': (gtk.STOCK_SAVE, gtk.RESPONSE_APPLY),
'open': (gtk.STOCK_OPEN, gtk.RESPONSE_APPLY)}
CHOOSER_TYPES = {'open': gtk.FILE_CHOOSER_ACTION_OPEN,
'save': gtk.FILE_CHOOSER_ACTION_SAVE}
FILTERS = {'catalogs': {'name': "Catalog files",
'patterns': ("*.sqlite", "*.sqlite.bz2")},
'all': {'name': "All files", 'patterns': ("*.*",)}}
def __init__(self, title="", buttons=('cancel', 'ok'), path=None,
chooser_type="open"):
super(ChooseFile, self).__init__()
self.path = path
self.title = title
self.action = self.CHOOSER_TYPES[chooser_type]
self.buttons = []
for button in buttons:
self.buttons.append(self.BUTTON_PAIRS[button][0])
self.buttons.append(self.BUTTON_PAIRS[button][1])
self.buttons = tuple(self.buttons)
self.confirmation = False
self.dialog = None
self.filters = []
def _mk_dialog(self):
"""
Create FileChooserDialog object
"""
self.dialog = gtk.FileChooserDialog(self.title, None, self.action,
self.buttons)
self.dialog.set_action(gtk.FILE_CHOOSER_ACTION_SAVE)
self.dialog.set_default_response(gtk.RESPONSE_OK)
self.dialog.set_do_overwrite_confirmation(self.confirmation)
self.dialog.set_title(self.title)
if self.URI:
self.dialog.set_current_folder_uri(self.URI)
elif self.path and os.path.exists(self.path):
self.path = "file://" + os.path.abspath(self.path)
self.dialog.set_current_folder_uri(self.path)
for filtr in self._get_filters():
self.dialog.add_filter(filtr)
def _get_filters(self):
"""
"""
filters = []
for filter_def in self.filters:
filtr = gtk.FileFilter()
filtr.set_name(self.FILTERS[filter_def]['name'])
for pat in self.FILTERS[filter_def]['patterns']:
filtr.add_pattern(pat)
filters.append(filtr)
return filters
def run(self):
"""
Show dialog, get response.
Returns:
Returns: String - with filename, None otherwise.
"""
if self.dialog is None:
self._mk_dialog()
response = self.dialog.run()
filename = None
if response == gtk.RESPONSE_APPLY:
filename = self.dialog.get_filename()
self.__class__.URI = self.dialog.get_current_folder_uri()
self.dialog.destroy()
return filename
def yesno(message, secondarymsg="", title="", default=False):
"""Question with yes-no buttons. Returns False on 'no', True on 'yes'"""
dialog = Dialog(gtk.MESSAGE_QUESTION, message, secondarymsg, title)
dialog.buttons = gtk.BUTTONS_YES_NO
dialog.ok_default = default
return dialog.run()
def okcancel(message, secondarymsg="", title="", default=False):
"""Question with ok-cancel buttons. Returns False on 'cancel', True on
'ok'"""
dialog = Dialog(gtk.MESSAGE_QUESTION, message, secondarymsg, title)
dialog.buttons = gtk.BUTTONS_OK_CANCEL
dialog.ok_default = default
return dialog.run()
def info(message, secondarymsg="", title="", button=gtk.BUTTONS_OK):
"""Info dialog. Button defaults to gtk.BUTTONS_OK, but can be changed with
gtk.BUTTONS_CANCEL, gtk.BUTTONS_CLOSE or gtk.BUTTONS_NONE.
Always returns True."""
dialog = Dialog(gtk.MESSAGE_INFO, message, secondarymsg, title)
dialog.buttons = button
dialog.run()
return True
def warn(message, secondarymsg="", title="", button=gtk.BUTTONS_OK):
"""Warning dialog. Button defaults to gtk.BUTTONS_OK, but can be changed
with gtk.BUTTONS_CANCEL, gtk.BUTTONS_CLOSE or gtk.BUTTONS_NONE.
Always returns True."""
dialog = Dialog(gtk.MESSAGE_WARNING, message, secondarymsg, title)
dialog.buttons = button
dialog.run()
return True
def error(message, secondarymsg="", title="", button=gtk.BUTTONS_OK):
"""Error dialog. Button defaults to gtk.BUTTONS_OK, but can be changed with
gtk.BUTTONS_CANCEL, gtk.BUTTONS_CLOSE or gtk.BUTTONS_NONE.
Always returns True."""
dialog = Dialog(gtk.MESSAGE_ERROR, message, secondarymsg, title)
dialog.buttons = button
dialog.run()
return True
def open_catalog(title=_("Open catalog"), path=None):
"""
Request filename from user to open.
Returns: string - full path and filename or None
"""
requester = ChooseFile(title)
requester.filters = ['catalogs', 'all']
return requester.run()
def save_catalog(title=_("Open catalog"), path=None):
"""
Request filename from user for save.
Returns: string - full path and filename or None
"""
requester = ChooseFile(title, chooser_type="save")
requester.filters = ['catalogs', 'all']
requester.confirmation = True
return requester.run()
def about():
"""
Show About dialog
"""
dialog = gtk.AboutDialog()
dialog.set_version(pygtktalog.__version__)
dialog.set_program_name(pygtktalog.__appname__)
dialog.set_copyright(pygtktalog.__copyright__)
dialog.set_comments(pygtktalog.__summary__)
dialog.set_website(pygtktalog.__web__)
dialog.set_logo(gtk.gdk.pixbuf_new_from_file(\
os.path.join(os.path.dirname(__file__), pygtktalog.__logo_img__)))
dialog.run()
dialog.destroy()

3
requirements.txt Normal file
View File

@@ -0,0 +1,3 @@
Pillow
exifread
sqlalchemy

30
setup.py Executable file
View File

@@ -0,0 +1,30 @@
#!/usr/bin/env python2
"""
Setup for the pyGTKtalog project
"""
from distutils.core import setup
setup(name='pygtktalog',
packages=['pygtktalog'],
version='2.0',
description='Catalog application with GTK interface',
author='Roman Dobosz',
author_email='gryf73@gmail.com',
url='https://github.com/gryf/pygtktalog',
download_url='https://github.com/gryf/pygtktalog.git',
keywords=['catalog', 'gwhere', 'where is it', 'collection', 'GTK'],
requires=['Pillow', 'sqlalchemy'],
scripts=['scripts/cmdcatalog.py'],
classifiers=['Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 2 :: Only',
'Development Status :: 4 - Beta',
'Environment :: Console',
'Intended Audience :: End Users/Desktop',
'License :: OSI Approved :: BSD License',
'Operating System :: OS Independent',
'Topic :: Multimedia :: Graphics'],
long_description=open('README.rst').read(),
options={'test': {'verbose': False,
'coverage': False}})

4
test-requirements.txt Normal file
View File

@@ -0,0 +1,4 @@
pytest
pytest-cov
pytest-pep8
coverage

View File

@@ -1,77 +0,0 @@
"""
Project: pyGTKtalog
Description: Test simple dialogs
Type: test
Author: Roman 'gryf' Dobosz, gryf73@gmail.com
Created: 2009-05-19
"""
import unittest
import os
import gtk
from pygtktalog.dialogs import Dialog, yesno, okcancel, info, warn, error
class MessageDialogMock(gtk.MessageDialog):
"""Mock class for MessageDialog, which shouldn't be displayed in a test"""
def run(self):
"""Carefull! only for MESSAGE_INFO return value is RESPONSE_OK!"""
if self.get_property('message-type') == gtk.MESSAGE_INFO:
return gtk.RESPONSE_OK
else:
return gtk.RESPONSE_CANCEL
class TestDialog(unittest.TestCase):
"""Tests for Dialog class"""
def test_dialog_create(self):
"""Test dialog creation and run method"""
# overwrite MessageDialog class in gtk module
gtk.MessageDialog = MessageDialogMock
dialog = Dialog(gtk.MESSAGE_INFO, 'msg', 'secondarymsg', 'title')
self.assertTrue(dialog.buttons == gtk.BUTTONS_OK, "dialog should have"
" gtk.BUTTONS_OK")
self.assertTrue(dialog.run(), "dialog should return True")
dialog = Dialog(gtk.MESSAGE_QUESTION, 'msg', 'secondarymsg', 'title')
self.assertFalse(dialog.run(), "dialog should return False")
# NOTE: dialog should be run before test against buttons attribute
self.assertTrue(dialog.buttons == gtk.BUTTONS_YES_NO,
"dialog should have gtk.BUTTONS_YES_NO")
dialog = Dialog(gtk.MESSAGE_QUESTION, 'msg', 'secondarymsg', 'title')
dialog.buttons = gtk.BUTTONS_OK
dialog.ok_default = True
self.assertFalse(dialog.run(), "dialog should return True")
def test_error(self):
"""Test error function"""
result = error('msg', 'secondarymsg', 'title')
self.assertTrue(result, "Should return True")
def test_warn(self):
"""Test warn function"""
result = warn('msg', 'secondarymsg', 'title')
self.assertTrue(result, "Should return True")
def test_info(self):
"""Test info function"""
result = info('msg', 'secondarymsg', 'title')
self.assertTrue(result, "Should return True")
def test_yesno(self):
"""Test yesno function"""
result = yesno('msg', 'secondarymsg', 'title')
self.assertFalse(result, "Should return False")
def test_okcancel(self):
"""Test yesno function"""
result = okcancel('msg', 'secondarymsg', 'title')
self.assertFalse(result, "Should return False")
if __name__ == "__main__":
os.chdir(os.path.join(os.path.abspath(os.path.dirname(__file__)), "../"))
unittest.main()

23
tox.ini Normal file
View File

@@ -0,0 +1,23 @@
[tox]
envlist = cleanup,py27,pep8
usedevelop = True
[testenv]
usedevelop=True
setenv = COVERAGE_FILE = .coverage
commands = py.test --cov=pygtktalog --cov-report=term-missing
deps = -r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt
[testenv:pep8]
usedevelop=True
commands = py.test --pep8 -m pep8
deps = -r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt
[testenv:cleanup]
setenv =
COVERAGE_FILE = .coverage
deps = coverage
commands = coverage erase