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__/
|
__pycache__/
|
||||||
*.py[cod]
|
*.py[cod]
|
||||||
|
.coverage
|
||||||
|
.tox
|
||||||
|
tags
|
||||||
|
MANIFEST
|
||||||
|
.cache
|
||||||
|
pygtktalog.egg-info
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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