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:
6
.gitignore
vendored
6
.gitignore
vendored
@@ -1,2 +1,8 @@
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
.coverage
|
||||
.tox
|
||||
tags
|
||||
MANIFEST
|
||||
.cache
|
||||
pygtktalog.egg-info
|
||||
|
||||
@@ -6,12 +6,11 @@
|
||||
Created: 2009-05-05
|
||||
"""
|
||||
|
||||
__version__ = "1.9.0"
|
||||
__version__ = "2.0.0"
|
||||
__appname__ = "pyGTKtalog"
|
||||
__copyright__ = u"\u00A9 Roman 'gryf' Dobosz"
|
||||
__summary__ = "%s is simple tool for managing file collections." % __appname__
|
||||
__web__ = "http://bitbucket.org/gryf"
|
||||
__logo_img__ = "views/pixmaps/Giant Worms.png"
|
||||
__web__ = "http://github.com/gryf/pygtktalog"
|
||||
|
||||
import os
|
||||
import sys
|
||||
@@ -19,15 +18,10 @@ import locale
|
||||
import gettext
|
||||
import __builtin__
|
||||
|
||||
import gtk.glade
|
||||
|
||||
from pygtktalog.logger import get_logger
|
||||
|
||||
|
||||
__all__ = ['controllers',
|
||||
'models',
|
||||
'views',
|
||||
'EXIF',
|
||||
__all__ = ['EXIF',
|
||||
'dbcommon',
|
||||
'dbobjects',
|
||||
'dialogs',
|
||||
@@ -48,12 +42,12 @@ except locale.Error:
|
||||
# unknown locale string, fallback to C
|
||||
locale.setlocale(locale.LC_ALL, 'C')
|
||||
|
||||
for module in gtk.glade, gettext:
|
||||
if os.path.exists(LOCALE_PATH):
|
||||
module.bindtextdomain(GETTEXT_DOMAIN, LOCALE_PATH)
|
||||
else:
|
||||
module.bindtextdomain(GETTEXT_DOMAIN)
|
||||
module.textdomain(GETTEXT_DOMAIN)
|
||||
# for module in gtk.glade, gettext:
|
||||
# if os.path.exists(LOCALE_PATH):
|
||||
# module.bindtextdomain(GETTEXT_DOMAIN, LOCALE_PATH)
|
||||
# else:
|
||||
# module.bindtextdomain(GETTEXT_DOMAIN)
|
||||
# module.textdomain(GETTEXT_DOMAIN)
|
||||
|
||||
# register the gettext function for the whole interpreter as "_"
|
||||
__builtin__._ = gettext.gettext
|
||||
|
||||
@@ -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
3
requirements.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
Pillow
|
||||
exifread
|
||||
sqlalchemy
|
||||
30
setup.py
Executable file
30
setup.py
Executable 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
4
test-requirements.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
pytest
|
||||
pytest-cov
|
||||
pytest-pep8
|
||||
coverage
|
||||
@@ -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
23
tox.ini
Normal 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
|
||||
Reference in New Issue
Block a user