"…mais ce serait peut-être l'une des plus grandes opportunités manquées de notre époque si le logiciel libre ne libérait rien d'autre que du code…"

Infos python: bytecodes, python parser, AST, gajim

Posted by patrick sur décembre 19, 2008

http://spyrit.svn.sourceforge.net/viewvc/spyrit/trunk/dist (‘A la question: Comment concentrer en un seul script toutes les classes et fonctions nécessaires (mais seulement ce qui est nécessaire) pour obtenir le résultat ? Sundance  a répondu : j’ai développé un petit système qui permet de faire ce genre de chose: tu lances ce programme en lui passant en paramètre le nom du script à packager, et ça cherche les modules dont dépend ce script, ça les compile en bytecode, et ça génère un seul script contenant 1) le bytecode des modules dans un dictionnaire, et 2) un hook d’import qui cherche les imports dans ce dictionnaire. »)

#!/usr/bin/python
## -*- coding: utf-8 -*-

import sys
import imp
import bz2
import time
import struct
import marshal
import os.path

LAUNCHER_STUB = """#!/usr/bin/python
## -*- coding: utf-8 -*-

EMBEDDED_MODULES = {
%s
}

import sys
import imp
import bz2
import marshal

class embedded_module_importer:

  def find_module( s, fullname, path=None ):

    if fullname == "MAIN":
      fullname = "__main__"

    return EMBEDDED_MODULES.has_key( fullname ) and s or None

  def load_module( s, fullname ):

    if fullname == "MAIN":
      fullname = "__main__"

    filename, code = EMBEDDED_MODULES[ fullname ]
    code =  marshal.loads( bz2.decompress( code ) )

    mod = sys.modules.setdefault( fullname, imp.new_module( fullname ) )
    mod.__file__ = filename
    mod.__loader__ = s

    exec code in mod.__dict__

    return mod

sys.meta_path.append( embedded_module_importer() )

import MAIN
"""

def get_timestamp_long():
  return struct.pack( "l", long( time.time() ) )

def make_bytecode( filename ):

  m  = compile( file( filename ).read(), filename, 'exec' )
#  bc = imp.get_magic() + get_timestamp_long() + marshal.dumps( m )
  bc = bz2.compress( marshal.dumps( m ) )

  return bc

def make_module_dict( modules ):

  mods = []

  for ( modulename, f ) in modules:
    bc = make_bytecode( f )
    mods.append( "  %s: ( %s, %s )" % ( modulename.__repr__(),
                                        f.__repr__(),
                                        make_bytecode( f ).__repr__() ) )

  return ",\n".join( mods )

def make_launcher( main, modules ):

  return LAUNCHER_STUB % ( make_module_dict( modules ) )

def build( scriptname, outputname=None ):

  mainname, ext = os.path.splitext( scriptname )

  from modulefinder import ModuleFinder

  p = os.path.abspath( os.getcwd() )

  if os.path.dirname( scriptname ):
    os.chdir( os.path.dirname( scriptname ) )

  mf = ModuleFinder( [ "." ] )
  mf.run_script( os.path.basename( scriptname ) )

  libs = [ ( name, mod.__file__ ) for ( name, mod ) in mf.modules.iteritems()
                                  if mod.__file__ ]

  output = make_launcher( mainname, libs )

  os.chdir( p )

  if not outputname:
    print output

  else:
    file( outputname, "wb" ).write( output )

def main():

  if not len( sys.argv ) > 1:
    return

  if len( sys.argv ) > 2:
    build( sys.argv[1], sys.argv[2] )

  else:
    build( sys.argv[1] )

if __name__ == "__main__":
  main()

Dans le même genre de choses:

http://svn.python.org/view/python/branches/release30-maint/Tools/freeze/README?rev=67499&view=markup (‘What is Freeze ? Freeze make it possible to ship arbitrary Python programs to people who don’t have Python. The shipped file (called a « frozen » version of your Python program) is an executable, so this only works if your platform is compatible with that on the receiving end (this is usually a matter of having the same major operating system revision and CPU type). ‘)

http://svn.python.org/view/python/branches/release30-maint/Python/compile.c?rev=67499&view=markup(‘This file compiles an abstract syntax tree (AST) into Python bytecode‘)

http://svn.python.org/view/python/branches/release30-maint/Python/ast.c?rev=67499&view=markup(‘This file includes functions to transform a concrete syntax tree (CST) to * an abstract syntax tree (AST). The main function is PyAST_FromNode()‘)

http://pypi.python.org/pypi/sourcecodegen/0.6.2 (‘This package provides a module-level source-code generator which
operates on the AST from the built-in compiler.ast module.Note that this AST is not compatible with the new ast module in
Python 2.6

The generator works on AST parse trees.

from compiler import parse
tree = parse("""\
...     print 'Hello, world!'
... """)

We can now generate Python-code equivalent to the original using the source-code generator.

from sourcecodegen import ModuleSourceCodeGenerator
generator = ModuleSourceCodeGenerator(tree)
print generator.getSourceCode()
print 'Hello, world!'

‘)

http://svn.python.org/view/python/branches/release30-maint/Demo/parser/#dirlist
http://svn.python.org/view/python/branches/release30-maint/Demo/parser/README?rev=67499&view=markup (‘These files are from the large example of using the `parser’ module. Refer
to the Python Library Reference for more information.
It also contains examples for the AST parser.

Files:
——

FILES — list of files associated with the parser module.

README — this file.

example.py — module that uses the `parser’ module to extract
information from the parse tree of Python source
code.

docstring.py — sample source file containing only a module docstring.

simple.py — sample source containing a « short form » definition.

source.py — sample source code used to demonstrate ability to
handle nested constructs easily using the functions
and classes in example.py.

test_parser.py program to put the parser module through its paces.

unparse.py AST (2.5) based example to recreate source code
from an AST. This is incomplete; contributions
are welcome.

Enjoy!‘)

http://svn.python.org/view/python/branches/release30-maint/Doc/library/parser.rst?rev=67499&view=markup (‘Access parse trees for Python source code…From Python 2.5 onward, it’s much more convenient to cut in at the Abstract  Syntax Tree (AST) generation and compilation stage, using the :mod:`ast` module’)

http://linuxfr.org/2008/12/18/24812.html(‘Gajim, le client Jabber aérien (écrit en Python et GTK+ pour ceux que ça intéresse) vient de sortir en version 0.12, quasiment un an jour pour jour après la 0.11.4 et deux ans après la 0.11.
L’avantage par rapport à d’autres de ce client de messagerie instantanée, sous licence GPLv3, est qu’il ne fait que le protocole Jabber (XMPP), et le fait bien. On a même accès à une console XML dans laquelle on peut injecter le XML qu’on veut, très fun pour jouer avec les copains pendant ces froides soirées d’hiver. Gros plus non négligeable, il est l’un des rares à prendre en charge GnuPG (peut-être même le seul en GTK+), pour la confidentialité de vos conversations ou pour authentifier votre interlocuteur.
Au programme des nouveautés :

  • Amélioration du support des sessions ;
  • Chiffrement point à point (transparent pour l’utilisateur) ;
  • Amélioration de l’interface graphique en général ;
  • Validation des certificats SSL ;
  • Intégration de Kerberos ;
  • Salons de discussion dans le roster ;
  • Conversion d’une conversation privée en salon de discussion ;
  • Événements personnels (PEP) : humeur, activité, musique écoutée ;
  • Et bien sûr, la classique corrections des bugs.

Il ne reste qu’à l’installer😉

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s

 
%d blogueurs aiment cette page :