Home > Dai forum, Debian, Debianizzazione, Gnome, Guide, Linux, LQH, Pacchetti, Ubuntu > Debianizzare un programma Python #5

Debianizzare un programma Python #5

11 giugno 2010

Questa guida a puntate riporterà i passaggi necessari dalla pacchettizzazione fino all’inclusione ufficiale di un software scritto in Python (Gespeaker) su Debian e più avanti su Ubuntu. Ogni giorno per circa un mese sarà descritto un passaggio da seguire per poter debianizzare così un proprio software.

#5 setup.py per distutils

Distutils è un sistema python studiato per le installazioni dei pacchetti, non solo per Debian e il file setup.py rappresenta il suo utilizzo più comune.

Vediamo il mio setup.py com’è strutturato:

#!/usr/bin/env python

##
#   Project: gespeaker - A GTK frontend for espeak  
#    Author: Fabio Castelli <muflone@XXXXXX.net>
# Copyright: 2009 Fabio Castelli
#   License: GPL-2+
#  This program is free software; you can redistribute it and/or modify it
#  under the terms of the GNU General Public License as published by the Free
#  Software Foundation; either version 2 of the License, or (at your option)
#  any later version.
#
#  This program is distributed in the hope that it will be useful, but WITHOUT
#  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
#  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
#  more details.
#
# On Debian GNU/Linux systems, the full text of the GNU General Public License
# can be found in the file /usr/share/common-licenses/GPL-2.
##

from distutils.core import setup
from distutils.command.install_data import install_data
from distutils.dep_util import newer
from distutils.log import info
import glob
import os
import sys

class InstallData(install_data):
  def run (self):
    self.data_files.extend (self._compile_po_files())
    install_data.run(self)

  def _compile_po_files(self):
    data_files = []

    # Don't install language files on win32
    if sys.platform == 'win32':
      return data_files

    PO_DIR = 'po'
    for po in glob.glob (os.path.join (PO_DIR,'*.po')):
      lang = os.path.basename(po[:-3])
      mo = os.path.join('build', 'mo', lang, 'gespeaker.mo')

      directory = os.path.dirname(mo)
      if not os.path.exists(directory):
        info('creating %s' % directory)
        os.makedirs(directory)

      if newer(po, mo):
        # True if mo doesn't exist
        cmd = 'msgfmt -o %s %s' % (mo, po)
        info('compiling %s -> %s' % (po, mo))
        if os.system(cmd) != 0:
          raise SystemExit('Error while running msgfmt')

        dest = os.path.dirname(os.path.join('share', 'locale',
          lang, 'LC_MESSAGES', 'gespeaker.mo'))
        data_files.append((dest, [mo]))

    return data_files

setup(name='Gespeaker',
  version='0.7',
  description='A GTK+ frontend for eSpeak and mbrola',
  author='Fabio Castelli',
  author_email='muflone@XXXXXX.net',
  url='http://code.google.com/p/gespeaker/',
  license='GPL v2',
  scripts=['gespeaker'],
  data_files=[
    ('share/applications', ['data/gespeaker.desktop']),
    ('share/man/man1', ['man/gespeaker.1']),
    ('share/doc/gespeaker', ['doc/README', 'doc/changelog']),
    ('share/gespeaker/data', ['data/testing.wav']),
    ('share/gespeaker/data/icons', glob.glob('data/icons/*')),
    ('share/gespeaker/data/ui', glob.glob('data/ui/*.glade')),
    ('share/gespeaker/src', glob.glob('src/*.py')),
  ],
  cmdclass={'install_data': InstallData}
)

La funzione _compile_po_files si occuperà di compilare in gespeaker.mo i vari files .po della lingua richiamando il comando shell

msgfmt -o <file mo> <file po>

Di volta in volta ciascun file sarà compilato nella cartella col nome della lingua.

In fondo allo script v’è il richiamo alla funzione principale setup con i vari argomenti, abbastanza chiari da spiegarsi da soli.

L’argomento scripts conterrà la lista dei files eseguibili da installare nel percorso dei files eseguibili (generalmente /usr/bin).

L’argomento data_files conterrà invece i vari files di dati che compongono l’applicazione.

Ciascun gruppo di files sarà formato da una directory di destinazione e da una lista di files origine. Ecco che dentro share/applications verrà copiato il file data/gespeaker.desktop, dentro share/doc/gespeaker verranno copiati i due files doc/README e doc/changelog e così via.

La funzione glob.glob elencherà tutti i files corrispondenti al pattern indicato, ad esempio dentro share/gespeaker/src saranno posti tutti i files con estensione .py che si trovano dentro la directory src.

Questa lunga lista (data_files) di files sarà poi estesa richiamando il metodo run della classe e includendo in essa anche i files .mo compilati dai .po.

Inizialmente ho avuto anche io qualche problema a comprendere l’utilità di questo sistema e il funzionamento di setup.py. Mi sono quindi limitato a copiare un setup.py altrui, adattato al mio applicativo, almeno all’inizio si consiglia di fare in questa maniera, adattando ovviamente i percorsi dei files a quelli propri.

Questo file verrà poi utilizzato dagli strumenti di impacchettamento, per cui non è necessario richiamarlo manualmente.

%d blogger cliccano Mi Piace per questo: