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 .project
.pydevproject .pydevproject
.settings .settings
.ropeproject
tags tags
*.pyc *.pyc

View file

@ -15,14 +15,17 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
"""Handle the basic configuration of Lutris."""
import os import os
import yaml import yaml
import logging import logging
from os.path import join from os.path import join
import lutris.pga as pga
import lutris.constants as constants import lutris.constants as constants
from lutris.settings import PGA_PATH from lutris.settings import PGA_PATH
from lutris.constants import CONFIG_EXTENSION, GAME_CONFIG_PATH
def check_config(): def check_config():
@ -43,7 +46,6 @@ def check_config():
os.mkdir(config_path) os.mkdir(config_path)
if not os.path.isfile(PGA_PATH): if not os.path.isfile(PGA_PATH):
import lutris.pga as pga
pga.create() pga.create()
@ -69,13 +71,14 @@ class LutrisConfig():
#By default config type is system, it can also be runner and game #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 #this means that when you call lutris_config_instance["key"] is will
#pick up the right configuration depending of config_type #pick up the right configuration depending of config_type
self.config_type = "system"
if runner: if runner:
self.runner = runner self.runner = runner
self.config_type = "runner" self.config_type = "runner"
elif game: elif game:
self.game = game self.game = game
self.config_type = "game" self.config_type = "game"
else:
self.config_type = "system"
#Read system configuration #Read system configuration
if os.path.exists(constants.system_config_full_path): if os.path.exists(constants.system_config_full_path):
@ -87,31 +90,32 @@ class LutrisConfig():
file(constants.system_config_full_path, "w+") file(constants.system_config_full_path, "w+")
if self.game: if self.game:
game_config_full_path = os.path.join(constants.GAME_CONFIG_PATH, game_config_full_path = join(GAME_CONFIG_PATH,
self.game + constants.CONFIG_EXTENSION) self.game + CONFIG_EXTENSION)
if os.path.exists(game_config_full_path): if os.path.exists(game_config_full_path):
try: try:
content = file(game_config_full_path, 'r').read() content = file(game_config_full_path, 'r').read()
self.game_config = yaml.load(content) self.game_config = yaml.load(content)
self.runner = self.game_config["runner"] self.runner = self.game_config["runner"]
except yaml.scanner.ScannerError: 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: 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: except KeyError:
logging.debug("Runner key is mandatory !") logging.debug("Runner key is mandatory !")
if self.runner: if self.runner:
runner_config_full_path = os.path.join(constants.runner_config_path, runner_config_full_path = join(constants.runner_config_path,
self.runner + constants.CONFIG_EXTENSION) self.runner + CONFIG_EXTENSION)
if os.path.exists(runner_config_full_path): 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() self.update_global_config()
def __getitem__(self, key): 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": if self.config_type == "game":
value = self.game_config[key] value = self.game_config[key]
elif self.config_type == "runner": elif self.config_type == "runner":
@ -130,6 +134,7 @@ class LutrisConfig():
self.update_global_config() self.update_global_config()
def update_global_config(self): def update_global_config(self):
"""Update the global config dict."""
for key in self.system_config.keys(): for key in self.system_config.keys():
if key in self.config: if key in self.config:
self.config[key].update(self.system_config[key]) self.config[key].update(self.system_config[key])
@ -150,34 +155,35 @@ class LutrisConfig():
self.config[key] = self.game_config[key] self.config[key] = self.game_config[key]
def get_real_name(self): def get_real_name(self):
"""Return the real name of a game."""
return self.config["realname"] return self.config["realname"]
def remove(self, game_name): def remove(self, game_name):
logging.debug("removing %s" % game_name) """Delete the configuration file from disk."""
os.remove(join(constants.GAME_CONFIG_PATH,
game_name + constants.CONFIG_EXTENSION)) logging.debug("removing %s", game_name)
os.remove(join(GAME_CONFIG_PATH,
game_name + CONFIG_EXTENSION))
def is_valid(self): 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."""
""" if "runner" in self.game_config:
try: return True
self.runner_name = self.game_config["runner"] else:
except KeyError:
print "Error in %s config file : No runner" % self.game print "Error in %s config file : No runner" % self.game
return False return False
return True
def save(self, runner_type=None): def save(self, runner_type=None):
"""Save configuration file """Save configuration file
The way to save config files can be set by the type argument The way to save config files can be set by the type argument
or with self.config_type or with self.config_type
""" """
self.update_global_config() self.update_global_config()
logging.debug("Saving config (type %s)" % runner_type) logging.debug("Saving config (type %s)", runner_type)
logging.debug(self.config) logging.debug(self.config)
if runner_type is None: if runner_type is None:
runner_type = self.config_type runner_type = self.config_type
@ -187,15 +193,16 @@ class LutrisConfig():
file(constants.system_config_full_path, "w").write(yaml_config) file(constants.system_config_full_path, "w").write(yaml_config)
elif runner_type == "runner": elif runner_type == "runner":
runner_config_path = join(constants.runner_config_path, 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) file(runner_config_path, "w").write(yaml_config)
elif runner_type == "game": elif runner_type == "game":
if not self.game: if not self.game:
self.game = self.config["runner"] \ self.game = self.config["runner"] \
+ "-" + self.config["realname"].replace(" ", "_") + "-" + self.config["realname"].replace(" ", "_")
self.game_config_path = join(constants.GAME_CONFIG_PATH, game_config_path = join(GAME_CONFIG_PATH,
self.game.replace('/', '_') + constants.CONFIG_EXTENSION) self.game.replace('/', '_') + \
config_file = file(self.game_config_path, "w") CONFIG_EXTENSION)
config_file = file(game_config_path, "w")
config_file.write(yaml_config) config_file.write(yaml_config)
return self.game return self.game
else: else:
@ -203,7 +210,7 @@ class LutrisConfig():
print "i don't know how to save this yet" print "i don't know how to save this yet"
def get_path(self, default=None): 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 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 ## along with this program; if not, write to the Free Software
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
############################################################################### ###############################################################################
"""Misc widgets used in the GUI."""
import os import os
import gtk import gtk
import gobject import gobject
import pango import pango
import Image import Image
from lutris.downloader import Downloader from lutris.downloader import Downloader
from lutris.constants import COVER_PATH, DATA_PATH from lutris.constants import COVER_PATH, DATA_PATH
import lutris.constants import lutris.constants
@ -47,37 +49,46 @@ class GameTreeView(gtk.TreeView):
model = gtk.ListStore(str, gtk.gdk.Pixbuf, str) model = gtk.ListStore(str, gtk.gdk.Pixbuf, str)
model.set_sort_column_id(0, gtk.SORT_ASCENDING) model.set_sort_column_id(0, gtk.SORT_ASCENDING)
self.set_model(model) self.set_model(model)
tp = gtk.CellRendererPixbuf() image_cell = gtk.CellRendererPixbuf()
column = gtk.TreeViewColumn("Runner", tp, pixbuf=self.COL_ICON) column = gtk.TreeViewColumn("Runner", image_cell, pixbuf=self.COL_ICON)
self.append_column(column) self.append_column(column)
tr = gtk.CellRendererText() text_cell = gtk.CellRendererText()
tr.set_property("ellipsize", pango.ELLIPSIZE_END) text_cell.set_property("ellipsize", pango.ELLIPSIZE_END)
column = gtk.TreeViewColumn("Game", tr, markup=self.COL_TEXT) column = gtk.TreeViewColumn("Game", text_cell, markup=self.COL_TEXT)
self.append_column(column) self.append_column(column)
for game in sorted(games): if games:
self.add_row(game) for game in sorted(games):
self.add_row(game)
def add_row(self, game): def add_row(self, game):
"""Add a game in the treeview."""
model = self.get_model() 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, icon_path = os.path.join(lutris.constants.DATA_PATH,
'media/runner_icons', 'media/runner_icons',
game['runner'] + '.png') game['runner'] + '.png')
pix = gtk.gdk.pixbuf_new_from_file_at_size(icon_path, pix = gtk.gdk.pixbuf_new_from_file_at_size(icon_path,
ICON_SIZE, ICON_SIZE) ICON_SIZE, ICON_SIZE)
row = model.append([game['id'], pix, s, ]) row = model.append([game['id'], pix, label, ])
return row return row
def remove_row(self, model_iter): def remove_row(self, model_iter):
"""Remove a game from the treeview."""
model = self.get_model() model = self.get_model()
model.remove(model_iter) model.remove(model_iter)
def sort_rows(self): def sort_rows(self):
"""Sort the game list."""
model = self.get_model() model = self.get_model()
gtk.TreeModelSort(model) gtk.TreeModelSort(model)
class GameCover(gtk.Image): class GameCover(gtk.Image):
"""Widget displaing the selected game's cover"""
def __init__(self, parent=None): def __init__(self, parent=None):
super(GameCover, self).__init__() super(GameCover, self).__init__()
self.parent_window = parent self.parent_window = parent
@ -85,14 +96,15 @@ class GameCover(gtk.Image):
self.connect('drag_data_received', self.on_cover_drop) self.connect('drag_data_received', self.on_cover_drop)
def set_game_cover(self, name): def set_game_cover(self, name):
coverFile = os.path.join(COVER_PATH, name + ".jpg") """Change the cover currently displayed."""
if os.path.exists(coverFile): cover_file = os.path.join(COVER_PATH, name + ".jpg")
if os.path.exists(cover_file):
#Resize the image #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 dest_w = 250.0
h = cover_pixbuf.get_height() height = cover_pixbuf.get_height()
w = cover_pixbuf.get_width() width = cover_pixbuf.get_width()
dest_h = h * (dest_w / w) dest_h = height * (dest_w / width)
self.set_from_pixbuf(cover_pixbuf.scale_simple( self.set_from_pixbuf(cover_pixbuf.scale_simple(
int(dest_w), int(dest_w),
int(dest_h), int(dest_h),
@ -103,9 +115,11 @@ class GameCover(gtk.Image):
self.set_from_file(os.path.join(DATA_PATH, "media/background.png")) self.set_from_file(os.path.join(DATA_PATH, "media/background.png"))
def desactivate_drop(self): def desactivate_drop(self):
"""Deactivate DnD for the widget."""
self.drag_dest_unset() self.drag_dest_unset()
def activate_drop(self): def activate_drop(self):
"""Activate DnD for the widget."""
targets = [('text/plain', 0, 0), targets = [('text/plain', 0, 0),
('text/uri-list', 0, 0), ('text/uri-list', 0, 0),
('text/html', 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) gtk.gdk.ACTION_COPY | gtk.gdk.ACTION_DEFAULT | gtk.gdk.ACTION_MOVE)
def on_cover_drop(self, widget, context, x, y, selection, target, ts): 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 # TODO : Change mouse cursor if no game is selected
# of course, it must not be handled here # of course, it must not be handled here
file_path = selection.data.strip() file_path = selection.data.strip()
@ -138,6 +153,7 @@ class GameCover(gtk.Image):
class DownloadProgressBox(gtk.HBox): class DownloadProgressBox(gtk.HBox):
"""Progress bar used to monitor a file download."""
__gsignals__ = {'complete': (gobject.SIGNAL_RUN_LAST, __gsignals__ = {'complete': (gobject.SIGNAL_RUN_LAST,
gobject.TYPE_NONE, gobject.TYPE_NONE,
(gobject.TYPE_PYOBJECT,)), (gobject.TYPE_PYOBJECT,)),
@ -147,6 +163,7 @@ class DownloadProgressBox(gtk.HBox):
def __init__(self, params, cancelable=True): def __init__(self, params, cancelable=True):
gtk.HBox.__init__(self, False, 2) gtk.HBox.__init__(self, False, 2)
self.downloader = None
self.progressbar = gtk.ProgressBar() self.progressbar = gtk.ProgressBar()
self.progressbar.show() self.progressbar.show()
self.pack_start(self.progressbar, True) self.pack_start(self.progressbar, True)
@ -161,13 +178,16 @@ class DownloadProgressBox(gtk.HBox):
self.dest = params['dest'] self.dest = params['dest']
def start(self): def start(self):
"""Start downloading a file."""
print "starting to download %s" % self.url print "starting to download %s" % self.url
self.downloader = Downloader(self.url, self.dest) 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.cancel_button.set_sensitive(True)
self.downloader.start() self.downloader.start()
return timer_id
def progress(self): def progress(self):
"""Show download progress."""
progress = min(self.downloader.progress, 1) progress = min(self.downloader.progress, 1)
self.progressbar.set_fraction(progress) self.progressbar.set_fraction(progress)
percent = progress * 100 percent = progress * 100
@ -179,10 +199,12 @@ class DownloadProgressBox(gtk.HBox):
return False return False
return True return True
def __stop_download(self, widget): def __stop_download(self):
"""Stop the current download."""
self.downloader.kill = True self.downloader.kill = True
self.cancel_button.set_sensitive(False) self.cancel_button.set_sensitive(False)
def cancel(self): def cancel(self):
"""Cancel the current download."""
print "cancelling download" print "cancelling download"
self.downloader.kill() self.downloader.kill()

View file

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

View file

@ -1,19 +1,22 @@
from os.path import join, isdir, realpath """Utility module for creating an application wide logger."""
from os import makedirs
import logging import logging
import logging.handlers import logging.handlers
import xdg.BaseDirectory import xdg.BaseDirectory
cache_dir = realpath(join(xdg.BaseDirectory.xdg_cache_home, "lutris")) from os import makedirs
if not isdir(cache_dir): from os.path import join, isdir, realpath
makedirs(cache_dir)
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, loghandler = logging.handlers.RotatingFileHandler(LOG_FILENAME,
maxBytes=20971520, backupCount=5) maxBytes=20971520,
backupCount=5)
logger = logging.getLogger('Lutris') 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) loghandler.setFormatter(logformatter)
logger.setLevel(logging.INFO) logger.setLevel(logging.INFO)
logger.addHandler(loghandler) logger.addHandler(loghandler)