some pylint refactoring

This commit is contained in:
Mathieu Comandon 2012-02-27 18:17:10 +01:00
parent 8e1d09b80f
commit cc697348fc
5 changed files with 112 additions and 73 deletions

View file

@ -3,5 +3,6 @@ build
.project
.pydevproject
.settings
.ropeproject
tags
*.pyc

View file

@ -15,14 +15,17 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
"""Handle the basic configuration of Lutris."""
import os
import yaml
import logging
from os.path import join
import lutris.pga as pga
import lutris.constants as constants
from lutris.settings import PGA_PATH
from lutris.constants import CONFIG_EXTENSION, GAME_CONFIG_PATH
def check_config():
@ -43,7 +46,6 @@ def check_config():
os.mkdir(config_path)
if not os.path.isfile(PGA_PATH):
import lutris.pga as pga
pga.create()
@ -69,13 +71,14 @@ class LutrisConfig():
#By default config type is system, it can also be runner and game
#this means that when you call lutris_config_instance["key"] is will
#pick up the right configuration depending of config_type
self.config_type = "system"
if runner:
self.runner = runner
self.config_type = "runner"
elif game:
self.game = game
self.config_type = "game"
else:
self.config_type = "system"
#Read system configuration
if os.path.exists(constants.system_config_full_path):
@ -87,31 +90,32 @@ class LutrisConfig():
file(constants.system_config_full_path, "w+")
if self.game:
game_config_full_path = os.path.join(constants.GAME_CONFIG_PATH,
self.game + constants.CONFIG_EXTENSION)
game_config_full_path = join(GAME_CONFIG_PATH,
self.game + CONFIG_EXTENSION)
if os.path.exists(game_config_full_path):
try:
content = file(game_config_full_path, 'r').read()
self.game_config = yaml.load(content)
self.runner = self.game_config["runner"]
except yaml.scanner.ScannerError:
logging.debug("error parsing config file %s" % game_config_full_path)
logging.debug("error parsing config file %s",
game_config_full_path)
except yaml.parser.ParserError:
logging.debug("error parsing config file %s" % game_config_full_path)
logging.debug("error parsing config file %s",
game_config_full_path)
except KeyError:
logging.debug("Runner key is mandatory !")
if self.runner:
runner_config_full_path = os.path.join(constants.runner_config_path,
self.runner + constants.CONFIG_EXTENSION)
runner_config_full_path = join(constants.runner_config_path,
self.runner + CONFIG_EXTENSION)
if os.path.exists(runner_config_full_path):
self.runner_config = yaml.load(file(runner_config_full_path, 'r').read())
yaml_content = file(runner_config_full_path, 'r').read()
self.runner_config = yaml.load(yaml_content)
self.update_global_config()
def __getitem__(self, key):
"""Allow to access config data directly by keys.
"""
"""Allow to access config data directly by keys."""
if self.config_type == "game":
value = self.game_config[key]
elif self.config_type == "runner":
@ -130,6 +134,7 @@ class LutrisConfig():
self.update_global_config()
def update_global_config(self):
"""Update the global config dict."""
for key in self.system_config.keys():
if key in self.config:
self.config[key].update(self.system_config[key])
@ -150,34 +155,35 @@ class LutrisConfig():
self.config[key] = self.game_config[key]
def get_real_name(self):
"""Return the real name of a game."""
return self.config["realname"]
def remove(self, game_name):
logging.debug("removing %s" % game_name)
os.remove(join(constants.GAME_CONFIG_PATH,
game_name + constants.CONFIG_EXTENSION))
"""Delete the configuration file from disk."""
logging.debug("removing %s", game_name)
os.remove(join(GAME_CONFIG_PATH,
game_name + CONFIG_EXTENSION))
def is_valid(self):
"""Check the config data and return True if config is ok.
"""Check the config data and return True if config is ok."""
"""
try:
self.runner_name = self.game_config["runner"]
except KeyError:
if "runner" in self.game_config:
return True
else:
print "Error in %s config file : No runner" % self.game
return False
return True
def save(self, runner_type=None):
"""Save configuration file
The way to save config files can be set by the type argument
or with self.config_type
"""
self.update_global_config()
logging.debug("Saving config (type %s)" % runner_type)
logging.debug("Saving config (type %s)", runner_type)
logging.debug(self.config)
if runner_type is None:
runner_type = self.config_type
@ -187,15 +193,16 @@ class LutrisConfig():
file(constants.system_config_full_path, "w").write(yaml_config)
elif runner_type == "runner":
runner_config_path = join(constants.runner_config_path,
self.runner + constants.CONFIG_EXTENSION)
self.runner + CONFIG_EXTENSION)
file(runner_config_path, "w").write(yaml_config)
elif runner_type == "game":
if not self.game:
self.game = self.config["runner"] \
+ "-" + self.config["realname"].replace(" ", "_")
self.game_config_path = join(constants.GAME_CONFIG_PATH,
self.game.replace('/', '_') + constants.CONFIG_EXTENSION)
config_file = file(self.game_config_path, "w")
game_config_path = join(GAME_CONFIG_PATH,
self.game.replace('/', '_') + \
CONFIG_EXTENSION)
config_file = file(game_config_path, "w")
config_file.write(yaml_config)
return self.game
else:
@ -203,7 +210,7 @@ class LutrisConfig():
print "i don't know how to save this yet"
def get_path(self, default=None):
"""Get the path to install games for a given runner
"""Get the path to install games for a given runner.
Return False if it can't find an installation path
"""

View file

@ -18,12 +18,14 @@
## along with this program; if not, write to the Free Software
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
###############################################################################
"""Misc widgets used in the GUI."""
import os
import gtk
import gobject
import pango
import Image
from lutris.downloader import Downloader
from lutris.constants import COVER_PATH, DATA_PATH
import lutris.constants
@ -47,37 +49,46 @@ class GameTreeView(gtk.TreeView):
model = gtk.ListStore(str, gtk.gdk.Pixbuf, str)
model.set_sort_column_id(0, gtk.SORT_ASCENDING)
self.set_model(model)
tp = gtk.CellRendererPixbuf()
column = gtk.TreeViewColumn("Runner", tp, pixbuf=self.COL_ICON)
image_cell = gtk.CellRendererPixbuf()
column = gtk.TreeViewColumn("Runner", image_cell, pixbuf=self.COL_ICON)
self.append_column(column)
tr = gtk.CellRendererText()
tr.set_property("ellipsize", pango.ELLIPSIZE_END)
column = gtk.TreeViewColumn("Game", tr, markup=self.COL_TEXT)
text_cell = gtk.CellRendererText()
text_cell.set_property("ellipsize", pango.ELLIPSIZE_END)
column = gtk.TreeViewColumn("Game", text_cell, markup=self.COL_TEXT)
self.append_column(column)
for game in sorted(games):
self.add_row(game)
if games:
for game in sorted(games):
self.add_row(game)
def add_row(self, game):
"""Add a game in the treeview."""
model = self.get_model()
s = "%s \n<small>%s</small>" % (game['name'], game['runner'])
label = "%s \n<small>%s</small>" % \
(game['name'], game['runner'])
icon_path = os.path.join(lutris.constants.DATA_PATH,
'media/runner_icons',
game['runner'] + '.png')
pix = gtk.gdk.pixbuf_new_from_file_at_size(icon_path,
ICON_SIZE, ICON_SIZE)
row = model.append([game['id'], pix, s, ])
row = model.append([game['id'], pix, label, ])
return row
def remove_row(self, model_iter):
"""Remove a game from the treeview."""
model = self.get_model()
model.remove(model_iter)
def sort_rows(self):
"""Sort the game list."""
model = self.get_model()
gtk.TreeModelSort(model)
class GameCover(gtk.Image):
"""Widget displaing the selected game's cover"""
def __init__(self, parent=None):
super(GameCover, self).__init__()
self.parent_window = parent
@ -85,14 +96,15 @@ class GameCover(gtk.Image):
self.connect('drag_data_received', self.on_cover_drop)
def set_game_cover(self, name):
coverFile = os.path.join(COVER_PATH, name + ".jpg")
if os.path.exists(coverFile):
"""Change the cover currently displayed."""
cover_file = os.path.join(COVER_PATH, name + ".jpg")
if os.path.exists(cover_file):
#Resize the image
cover_pixbuf = gtk.gdk.pixbuf_new_from_file(coverFile)
cover_pixbuf = gtk.gdk.pixbuf_new_from_file(cover_file)
dest_w = 250.0
h = cover_pixbuf.get_height()
w = cover_pixbuf.get_width()
dest_h = h * (dest_w / w)
height = cover_pixbuf.get_height()
width = cover_pixbuf.get_width()
dest_h = height * (dest_w / width)
self.set_from_pixbuf(cover_pixbuf.scale_simple(
int(dest_w),
int(dest_h),
@ -103,9 +115,11 @@ class GameCover(gtk.Image):
self.set_from_file(os.path.join(DATA_PATH, "media/background.png"))
def desactivate_drop(self):
"""Deactivate DnD for the widget."""
self.drag_dest_unset()
def activate_drop(self):
"""Activate DnD for the widget."""
targets = [('text/plain', 0, 0),
('text/uri-list', 0, 0),
('text/html', 0, 0),
@ -115,6 +129,7 @@ class GameCover(gtk.Image):
gtk.gdk.ACTION_COPY | gtk.gdk.ACTION_DEFAULT | gtk.gdk.ACTION_MOVE)
def on_cover_drop(self, widget, context, x, y, selection, target, ts):
"""Take action based on a drop on the widget."""
# TODO : Change mouse cursor if no game is selected
# of course, it must not be handled here
file_path = selection.data.strip()
@ -138,6 +153,7 @@ class GameCover(gtk.Image):
class DownloadProgressBox(gtk.HBox):
"""Progress bar used to monitor a file download."""
__gsignals__ = {'complete': (gobject.SIGNAL_RUN_LAST,
gobject.TYPE_NONE,
(gobject.TYPE_PYOBJECT,)),
@ -147,6 +163,7 @@ class DownloadProgressBox(gtk.HBox):
def __init__(self, params, cancelable=True):
gtk.HBox.__init__(self, False, 2)
self.downloader = None
self.progressbar = gtk.ProgressBar()
self.progressbar.show()
self.pack_start(self.progressbar, True)
@ -161,13 +178,16 @@ class DownloadProgressBox(gtk.HBox):
self.dest = params['dest']
def start(self):
"""Start downloading a file."""
print "starting to download %s" % self.url
self.downloader = Downloader(self.url, self.dest)
self.timer_id = gobject.timeout_add(100, self.progress)
timer_id = gobject.timeout_add(100, self.progress)
self.cancel_button.set_sensitive(True)
self.downloader.start()
return timer_id
def progress(self):
"""Show download progress."""
progress = min(self.downloader.progress, 1)
self.progressbar.set_fraction(progress)
percent = progress * 100
@ -179,10 +199,12 @@ class DownloadProgressBox(gtk.HBox):
return False
return True
def __stop_download(self, widget):
def __stop_download(self):
"""Stop the current download."""
self.downloader.kill = True
self.cancel_button.set_sensitive(False)
def cancel(self):
"""Cancel the current download."""
print "cancelling download"
self.downloader.kill()

View file

@ -15,8 +15,9 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
"""Personnal Game Archive module. Handle local database of user's games."""
import unicodedata
import sqlite3
import re
@ -24,48 +25,53 @@ from lutris.settings import PGA_PATH
def slugify(value):
"""
"""Remove special characters from a string and slugify it.
Normalizes string, converts to lowercase, removes non-alpha characters,
and converts spaces to hyphens.
"""
import unicodedata
value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore')
value = unicode(re.sub('[^\w\s-]', '', value).strip().lower())
return re.sub('[-\s]+', '-', value)
def connect():
"""Connect to the local PGA database."""
return sqlite3.connect(PGA_PATH)
def create():
c = connect()
q = 'create table games (name text, slug text, machine text, runner text)'
c.execute(q)
c.commit()
c.close()
"""Create the local PGA database."""
con = connect()
query = 'create table games ' + \
'(name text, slug text, machine text, runner text)'
con.execute(query)
con.commit()
con.close()
def get_games(name_filter=None):
c = connect()
cur = c.cursor()
"""Get the list of every game in database."""
con = connect()
cur = con.cursor()
if filter is not None:
q = "select * from where name LIKE = ?"
rows = cur.execute(q, (name_filter, ))
query = "select * from where name LIKE = ?"
rows = cur.execute(query, (name_filter, ))
else:
q = "select * from games"
rows = cur.execute(q)
query = "select * from games"
rows = cur.execute(query)
results = rows.fetchall()
cur.close()
c.close()
con.close()
return results
def add_game(name, machine, runner):
"""Adds a game to the PGA database."""
slug = slugify(name)
c = connect()
c.execute("""insert into games(name, slug, machine, runner) values
con = connect()
con.execute("""insert into games(name, slug, machine, runner) values
(?, ?, ?, ?)""", (name, slug, machine, runner))
c.commit()
c.close()
con.commit()
con.close()

View file

@ -1,19 +1,22 @@
from os.path import join, isdir, realpath
from os import makedirs
"""Utility module for creating an application wide logger."""
import logging
import logging.handlers
import xdg.BaseDirectory
cache_dir = realpath(join(xdg.BaseDirectory.xdg_cache_home, "lutris"))
if not isdir(cache_dir):
makedirs(cache_dir)
from os import makedirs
from os.path import join, isdir, realpath
LOG_FILENAME = join(cache_dir, "lutris.log")
CACHE_DIR = realpath(join(xdg.BaseDirectory.xdg_cache_home, "lutris"))
if not isdir(CACHE_DIR):
makedirs(CACHE_DIR)
LOG_FILENAME = join(CACHE_DIR, "lutris.log")
loghandler = logging.handlers.RotatingFileHandler(LOG_FILENAME,
maxBytes=20971520, backupCount=5)
maxBytes=20971520,
backupCount=5)
logger = logging.getLogger('Lutris')
logformatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
log_format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
logformatter = logging.Formatter(log_format)
loghandler.setFormatter(logformatter)
logger.setLevel(logging.INFO)
logger.addHandler(loghandler)