- 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
So basically, pip’s requirements files are what Zope calls the “Known Good Set” and what Turbogears 2 does by maintaining its own PyPI server to distribute TG2 packages : a list of versions that are known to interact well in the same environment, right ?
But it’s not really different from setuptools there, except that you change the requirements in a different place if something goes wrong.
So to simplify the problem, couldn’t we have juste ONE requirement file in the whole Python ?
This could be the clue for os packagers : they would be able to tweak this file, while developers would be able to try out their package over different requirements files (”the debian etch python requirement file” “the debian unstable python requirement file”, etc). And for specific, isolated stuff, using virtualenv would allow developer to have their own custome requirement files….