Intégration de la branche release-7.0.0

This commit is contained in:
Jephté Clain 2017-08-25 15:54:18 +04:00
commit 9b13be8142
36 changed files with 179 additions and 50 deletions

View File

@ -1,3 +1,17 @@
## Version 7.0.0 du 25/08/2017-15:53
* `e4f154e` uawk: possibilité de lancer les versions locale-aware
* `ef00e07` bug
* `377ca5e` implémenter awkcsv2fsv. corriger un bug avec les outils qui utilisaient cawkrun à l'intérieur d'une fonction l*
* `2f448d5` ussh: problèmes de compatibilité
* `2cc2411` bug potentiel
* `65bd363` webpyapp: réorganiser les fichiers pour supporter des librairies locales
* `0b39b23` webpyapp: les variables de server.conf sont configurables
* `d1a1d4d` webpyapp: cosmetic
* `46fbec7` webpyapp: bootstrap facilité des sessions
* `c541958` webpyapp: support du mode développement
* `e2ea2ea` ufile: ajout de --force-cp
## Version 6.7.0 du 19/07/2017-15:45 ## Version 6.7.0 du 19/07/2017-15:45
* `1b92275` apacheconfig: support d'un script post-update.sh * `1b92275` apacheconfig: support d'un script post-update.sh

View File

@ -1 +1 @@
6.7.0 7.0.0

View File

@ -8,12 +8,12 @@ from os import path
from ulib.base.base import isstr, isbool, isnum, isflt, seqof, make_prop from ulib.base.base import isstr, isbool, isnum, isflt, seqof, make_prop
from ulib.base.uio import _u, Utf8IO from ulib.base.uio import _u, Utf8IO
from ulib.base.output import set_verbosity, enote, edebug from ulib.base.output import set_verbosity, einfo, enote, edebug
from ulib.base.args import get_args from ulib.base.args import get_args
from ulib.base.dates import rfc2822 from ulib.base.dates import rfc2822
from ulib.base.functions import apply_args from ulib.base.functions import apply_args
from ulib.base.words import plural from ulib.base.words import plural
from ulib.formats import unicodeF, booleanF, integerF, floatF from ulib.formats import unicodeF, strF, booleanF, integerF, floatF
from ulib.ext import web from ulib.ext import web
def checked(b): def checked(b):
@ -307,8 +307,13 @@ class Page(object):
def index(self): return self.render() def index(self): return self.render()
class ShConfig(dict): class ShConfig(dict):
def __init__(self, config, **defaults): _formats = None
super(ShConfig, self).__init__(**defaults) def __init__(self, config, formats):
super(ShConfig, self).__init__()
self._formats = formats
for name in formats.keys():
self[name] = None
inf = open(config, 'rb') inf = open(config, 'rb')
try: s = inf.read() try: s = inf.read()
finally: inf.close() finally: inf.close()
@ -321,10 +326,18 @@ class ShConfig(dict):
mo = self.RE_NAMEVALUE.match(part) mo = self.RE_NAMEVALUE.match(part)
if mo is None: continue #XXX ignorer pour le moment if mo is None: continue #XXX ignorer pour le moment
name, value = mo.groups() name, value = mo.groups()
self[name] = value format = self._formats.get(name, unicodeF)
self[name] = format.parse(value)
class Application(object): class Application(object):
CONFIG = 'server.conf' # si ce fichier existe dans basedir, alors forcer le mode développement: la
# variable HOST est ignorée et DEBUG vaut par défaut True
DEVEL_SF = '.devel'
# nom du fichier de configuration à charger automatiquement à partir de
# basedir. pour désactiver cette fonctionnalité, utiliser la valeur None
CONFIG_FILE = 'server.conf'
CONFIG_VARS = dict(HOST=strF, PORT=integerF, DEBUG=booleanF)
# configuration par défaut
HOST = '0.0.0.0' HOST = '0.0.0.0'
PORT = 12345 PORT = 12345
DEBUG = False DEBUG = False
@ -362,12 +375,17 @@ class Application(object):
templatedir = path.join(self.basedir, 'templates') templatedir = path.join(self.basedir, 'templates')
self.templatedir = templatedir self.templatedir = templatedir
config = path.join(self.basedir, self.CONFIG) devel = path.exists(path.join(self.basedir, self.DEVEL_SF))
if path.exists(config): if devel: einfo("Mode developpement activé")
c = ShConfig(config, HOST=None, PORT=None, DEBUG=None)
if host is None: host = c['HOST'] if self.CONFIG_FILE is not None:
if port is None: port = integerF.parse((c['PORT'])) config = path.join(self.basedir, self.CONFIG_FILE)
if debug is None: debug = booleanF.parse(c['DEBUG']) if path.exists(config):
c = ShConfig(config, self.CONFIG_VARS)
for name, value in c.items():
if devel and name == 'HOST': continue
if devel and name == 'DEBUG' and value is None: value = True
if value is not None: setattr(self, name, value)
if host is not None: self.HOST = host if host is not None: self.HOST = host
if port is not None: self.PORT = port if port is not None: self.PORT = port

View File

@ -1 +1 @@
014003000 015000000

View File

@ -841,7 +841,7 @@ function lawkcsv() {
reset_fields= reset_fields=
fi fi
awkrun -f \ lawkrun -f \
skip_lines:int="$skip" parse_headers:int="$parse_headers" \ skip_lines:int="$skip" parse_headers:int="$parse_headers" \
autosep:int="$autosep" colsep="$colsep" qchar="$qchar" echar="$echar" \ autosep:int="$autosep" colsep="$colsep" qchar="$qchar" echar="$echar" \
show_headers:int="$show_headers" reset_fields:int="$reset_fields" \ show_headers:int="$show_headers" reset_fields:int="$reset_fields" \
@ -978,7 +978,7 @@ function lgrepcsv() {
headers=("$@") headers=("$@")
if [ -z "${headers[*]}" ]; then if [ -z "${headers[*]}" ]; then
parse_headers=1 parse_headers=1
array_from_lines headers "$(awkrun -f lskip:int="$skip" 'NR <= lskip { next } array_from_lines headers "$(lawkrun -f lskip:int="$skip" 'NR <= lskip { next }
{ {
count = array_parsecsv(__fields, $0) count = array_parsecsv(__fields, $0)
for (i = 1; i <= count; i++) { for (i = 1; i <= count; i++) {
@ -1077,7 +1077,7 @@ function lawkfsv2csv() {
done done
shift shift
awkrun -f \ lawkrun -f \
skip_lines:int="$skip" trim_values:int="$rtrim" show_headers:int="$show_headers" \ skip_lines:int="$skip" trim_values:int="$rtrim" show_headers:int="$show_headers" \
headers[@] starts[@] sizes[@] \ headers[@] starts[@] sizes[@] \
"$__AWKCSV_FUNCTIONS"' "$__AWKCSV_FUNCTIONS"'
@ -1109,6 +1109,55 @@ function awkfsv2csv() { LANG=C lawkfsv2csv "$@"; }
################################################################################ ################################################################################
__AWKCSV2FSV_HELP="\
Transformer un flux csv en fsv (colonnes à largeurs fixes)
Chaque argument doit être de la forme field:size"
function lawkcsv2fsv() {
local -a args fieldsizes
if parse_opts @ args -- "$@"; then
set -- "${args[@]}"
else
eerror "$args"
return 1
fi
local -a fields sizes
local fieldsize field size
while [ $# -gt 0 -a "$1" != "--" ]; do
fieldsize="$1"
shift
splitpair "$fieldsize" field size
[ -n "$field" ] || {
eerror "field est requis"
return 1
}
[ -n "$size" ] || size=1
array_add fields "$field"
array_add sizes "$size"
done
shift
lawkcsv -v fields[@] -v sizes[@] -a '{
line = ""
for (i = 1; i <= fields_count; i++) {
size = sizes[i] + 0
value = get(fields[i]) ""
while (length(value) < size) value = value " "
if (length(value) > size) value = substr(value, 1, size)
line = line value
}
print line
}' -- "$@"
}
function cawkcsv2fsv() { LANG=C lawkcsv2fsv "$@"; }
function awkcsv2fsv() { LANG=C lawkcsv2fsv "$@"; }
################################################################################
__MERGECSV_HELP="\ __MERGECSV_HELP="\
Fusionner deux fichiers csv en faisant la correspondance sur la valeur d'un Fusionner deux fichiers csv en faisant la correspondance sur la valeur d'un
champ, qui est la clé champ, qui est la clé
@ -1264,14 +1313,14 @@ function lmergecsv() {
[ "$parse_headers" == "auto" ] && parse_headers=1 [ "$parse_headers" == "auto" ] && parse_headers=1
if [ -n "$parse_headers" ]; then if [ -n "$parse_headers" ]; then
[ -n "$lheaders" ] || lheaders="$(<"$lfile" awkrun lskip:int="$lskip" 'NR <= lskip { next } { print; exit }')" [ -n "$lheaders" ] || lheaders="$(<"$lfile" lawkrun lskip:int="$lskip" 'NR <= lskip { next } { print; exit }')"
[ -n "$rheaders" ] || rheaders="$(<"$rfile" awkrun lskip:int="$lskip" 'NR <= lskip { next } { print; exit }')" [ -n "$rheaders" ] || rheaders="$(<"$rfile" lawkrun lskip:int="$lskip" 'NR <= lskip { next } { print; exit }')"
fi fi
# faire le fichier de travail pour lfile # faire le fichier de travail pour lfile
local tmpleft local tmpleft
ac_set_tmpfile tmpleft "" __mergecsv_left "" __MERGECSV_DEBUG ac_set_tmpfile tmpleft "" __mergecsv_left "" __MERGECSV_DEBUG
<"$lfile" awkrun -f \ <"$lfile" lawkrun -f \
padding="$padding" padlen:int="$padlen" \ padding="$padding" padlen:int="$padlen" \
parse_headers:int="$parse_headers" ignore_case:int="$ignore_case" \ parse_headers:int="$parse_headers" ignore_case:int="$ignore_case" \
lskip:int="$lskip" lkey="$lkey" \ lskip:int="$lskip" lkey="$lkey" \
@ -1295,7 +1344,7 @@ parse_headers && do_once("parse-headers") {
# faire le fichier de travail pour rfile # faire le fichier de travail pour rfile
local tmpright local tmpright
ac_set_tmpfile tmpright "" __mergecsv_right "" __MERGECSV_DEBUG ac_set_tmpfile tmpright "" __mergecsv_right "" __MERGECSV_DEBUG
<"$rfile" awkrun -f \ <"$rfile" lawkrun -f \
padding="$padding" padlen:int="$padlen" \ padding="$padding" padlen:int="$padlen" \
parse_headers:int="$parse_headers" ignore_case:int="$ignore_case" \ parse_headers:int="$parse_headers" ignore_case:int="$ignore_case" \
rskip:int="$rskip" rkey="$rkey" \ rskip:int="$rskip" rkey="$rkey" \
@ -1409,7 +1458,7 @@ parse_headers && do_once("parse-headers") {
ac_set_tmpfile tmpmerged "" __mergecsv_merged "" __MERGECSV_DEBUG ac_set_tmpfile tmpmerged "" __mergecsv_merged "" __MERGECSV_DEBUG
csort -s -k 1,$(($padlen + 1)) "$tmpleft" "$tmpright" >"$tmpmerged" csort -s -k 1,$(($padlen + 1)) "$tmpleft" "$tmpright" >"$tmpmerged"
<"$tmpmerged" awkrun -f \ <"$tmpmerged" lawkrun -f \
padlen:int="$padlen" \ padlen:int="$padlen" \
parse_headers:int="$parse_headers" ignore_case:int="$ignore_case" \ parse_headers:int="$parse_headers" ignore_case:int="$ignore_case" \
lheaderscsv="$lheaders" lkey="$lkey" lprefix="$lprefix" \ lheaderscsv="$lheaders" lkey="$lkey" lprefix="$lprefix" \
@ -1700,14 +1749,14 @@ function lsortcsv() {
cat >"$tmpinput" cat >"$tmpinput"
input="$tmpinput" input="$tmpinput"
fi fi
headers="$(<"$input" awkrun skip:int="$skip" 'NR <= skip { next } { print; exit }')" headers="$(<"$input" lawkrun skip:int="$skip" 'NR <= skip { next } { print; exit }')"
fi fi
# faire le fichier de travail # faire le fichier de travail
local tmpinput local tmpinput
ac_set_tmpfile tmpinput "" __sortcsv_input "" __SORTCSV_DEBUG ac_set_tmpfile tmpinput "" __sortcsv_input "" __SORTCSV_DEBUG
array_add tmpfiles "$tmpinput" array_add tmpfiles "$tmpinput"
<"$input" >"$tmpinput" awkrun -f \ <"$input" >"$tmpinput" lawkrun -f \
padding="$padding" padlen:int="$padlen" \ padding="$padding" padlen:int="$padlen" \
skip:int="$skip" parse_headers:int="$parse_headers" \ skip:int="$skip" parse_headers:int="$parse_headers" \
key="$key" \ key="$key" \
@ -1740,7 +1789,7 @@ parse_headers && do_once("parse-headers") {
# résultat # résultat
[ -n "$output" ] || output=/dev/stdout [ -n "$output" ] || output=/dev/stdout
stdredir "$tmpsorted" "$output" "" awkrun -f \ stdredir "$tmpsorted" "$output" "" lawkrun -f \
padlen:int="$padlen" \ padlen:int="$padlen" \
headerscsv="$headers" show_headers:int="$show_headers" \ headerscsv="$headers" show_headers:int="$show_headers" \
' '
@ -2060,7 +2109,7 @@ function lprintcsv() {
[ -n "$output" ] || output=/dev/stdout [ -n "$output" ] || output=/dev/stdout
values=("$@") values=("$@")
stdredir "" ">>$output" "" awkrun -f fields[@] show_headers:int="$show_headers" values[@] ' stdredir "" ">>$output" "" lawkrun -f fields[@] show_headers:int="$show_headers" values[@] '
BEGIN { BEGIN {
if (show_headers) array_printcsv(fields) if (show_headers) array_printcsv(fields)
if (fields_count > 0) count = fields_count if (fields_count > 0) count = fields_count

View File

@ -14,7 +14,8 @@ function pkg_check() {
# Vérifier que les packages sont installés sur le système # Vérifier que les packages sont installés sur le système
local pkg status local pkg status
for pkg in "$@"; do for pkg in "$@"; do
status="$(LANG=C dpkg -s "$pkg" 2>/dev/null | grep '^Status:')" || return 1 LANG=C setx status=dpkg -s "$pkg" 2>/dev/null || return 1
setx status=grep '^Status:' <<<"$status"
[[ "$status" == *not-installed* ]] && return 1 [[ "$status" == *not-installed* ]] && return 1
[[ "$status" == *deinstall* ]] && return 1 [[ "$status" == *deinstall* ]] && return 1
done done

View File

@ -0,0 +1 @@
*.py[co]

View File

@ -57,7 +57,9 @@ fi
etitle "Copie des fichiers" etitle "Copie des fichiers"
destdir="$destdir/$name" destdir="$destdir/$name"
mkdir -p "$destdir" || die mkdir -p "$destdir" || die
rsync -a --exclude /server.conf --exclude /install-or-update.sh "$scriptdir/" "$destdir" rsync -a \
--exclude /server.conf --exclude /install-or-update.sh --exclude /.devel \
"$scriptdir/" "$destdir"
eend eend
etitle "Vérification de la configuration" etitle "Vérification de la configuration"

View File

@ -0,0 +1,4 @@
# -*- coding: utf-8 mode: python -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
__all__ = ()

View File

@ -3,19 +3,24 @@
__all__ = ('Server',) __all__ = ('Server',)
import sys, os
from os import path
SCRIPTDIR = path.abspath(path.split(__file__)[0])
sys.path.insert(0, path.join(SCRIPTDIR, 'lib/python'))
from ulib.web import web, Application, Page, defaults from ulib.web import web, Application, Page, defaults
class Server(Application): class Server(Application):
def __init__(self, basedir=None, templatedir=None, host=None, port=None, debug=None): def __init__(self, basedir=None, templatedir=None, host=None, port=None, debug=None):
Application.__init__(self, basedir, templatedir, host, port, debug) super(Server, self).__init__(basedir, templatedir, host, port, debug)
def _new_session(self):
pass # décommenter la ligne suivante pour activer les sessions
#return web.session.DiskStore('sessions'), {}
class index(Page): class index(Page):
PREFIX = r'/' PREFIX = r'/'
if __name__ == '__main__': if __name__ == '__main__':
import sys Server(SCRIPTDIR).run(sys.argv[1:])
from os import path
basedir = path.abspath(path.split(__file__)[0])
sys.path.append(path.join(basedir, 'lib'))
Server(basedir).run(sys.argv[1:])

View File

@ -0,0 +1,3 @@
/*
/*/
!/.gitignore

38
uawk
View File

@ -1,7 +1,7 @@
#!/bin/bash #!/bin/bash
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
TOOLS=(awkrun awkcsv grepcsv awkfsv2csv mergecsv sortcsv dumpcsv printcsv) TOOLS=(awkrun awkcsv grepcsv awkfsv2csv awkcsv2fsv mergecsv sortcsv dumpcsv printcsv)
if [ "$#" -eq 1 -a "$1" == --nutools-makelinks ]; then if [ "$#" -eq 1 -a "$1" == --nutools-makelinks ]; then
# créer les liens # créer les liens
scriptname="$(basename "$0")" scriptname="$(basename "$0")"
@ -45,13 +45,22 @@ fi
# Aliases pour les noms d'outils # Aliases pour les noms d'outils
case "$tool" in case "$tool" in
run) tool=awkrun;; run) tool=awkrun; toolprefix=; prefix=c; Clang=1;;
csv) tool=awkcsv;; lrun) tool=awkrun; toolprefix=l; prefix=l; Clang=;;
grep) tool=grepcsv;; csv) tool=awkcsv; toolprefix=; prefix=c; Clang=1;;
fsv2csv|fsv) tool=awkfsv2csv;; lcsv) tool=awkcsv; toolprefix=l; prefix=l; Clang=;;
merge) tool=mergecsv;; grep) tool=grepcsv; toolprefix=; prefix=c; Clang=1;;
sort) tool=sortcsv;; lgrep) tool=grepcsv; toolprefix=l; prefix=l; Clang=;;
dump) tool=dumpcsv;; fsv2csv|fsv) tool=awkfsv2csv; toolprefix=; prefix=c; Clang=1;;
lfsv2csv|lfsv) tool=awkfsv2csv; toolprefix=l; prefix=l; Clang=;;
csv2fsv) tool=awkcsv2fsv; toolprefix=; prefix=c; Clang=1;;
lcsv2fsv) tool=awkcsv2fsv; toolprefix=l; prefix=l; Clang=;;
merge) tool=mergecsv; toolprefix=; prefix=c; Clang=1;;
lmerge) tool=mergecsv; toolprefix=l; prefix=l; Clang=;;
sort) tool=sortcsv; toolprefix=; prefix=c; Clang=1;;
lsort) tool=sortcsv; toolprefix=l; prefix=l; Clang=;;
dump) tool=dumpcsv; toolprefix=; prefix=c; Clang=1;;
ldump) tool=dumpcsv; toolprefix=l; prefix=l; Clang=;;
esac esac
scriptname="$toolprefix$tool" scriptname="$toolprefix$tool"
@ -95,12 +104,23 @@ elif [ "$tool" == "awkfsv2csv" ]; then
${Clang:+note: ce script ne tient pas compte de la locale: il travaille avec LANG=C ${Clang:+note: ce script ne tient pas compte de la locale: il travaille avec LANG=C
} }
USAGE USAGE
$scriptname [options] -- [header:sizes...] [-- inputfiles...] $scriptname [options] -- [header:size,...] [-- inputfiles...]
$__AWKFSV2CSV_HELP" $__AWKFSV2CSV_HELP"
"${prefix}awkfsv2csv" "$@" "${prefix}awkfsv2csv" "$@"
elif [ "$tool" == "awkcsv2fsv" ]; then
[ $# -eq 1 -a "$1" == --help ] && exit_with uecho "$scriptname: wrapper autour de awk pour transformer un fichier à colonnes fixes en fichier csv
${Clang:+note: ce script ne tient pas compte de la locale: il travaille avec LANG=C
}
USAGE
$scriptname [options] -- [field:size,...] [-- inputfiles...]
$__AWKCSV2FSV_HELP"
"${prefix}awkcsv2fsv" "$@"
elif [ "$tool" == "mergecsv" ]; then elif [ "$tool" == "mergecsv" ]; then
[ $# -eq 1 -a "$1" == --help ] && exit_with uecho "$scriptname: fusionner deux fichiers csv sur un champ commun [ $# -eq 1 -a "$1" == --help ] && exit_with uecho "$scriptname: fusionner deux fichiers csv sur un champ commun
${Clang:+note: ce script ne tient pas compte de la locale: il travaille avec LANG=C ${Clang:+note: ce script ne tient pas compte de la locale: il travaille avec LANG=C

8
ufile
View File

@ -44,6 +44,11 @@ OPTIONS
défaut ~/etc/default/ufile défaut ~/etc/default/ufile
--file --file
Classer les fichiers spécifiés. C'est l'action par défaut Classer les fichiers spécifiés. C'est l'action par défaut
--force-cp
Spécifier le mode de classement des fichiers. Par défaut, le fichier est
déplacé dans la destination s'il s'agit d'un classement local, ou copié
s'il s'agit d'un classement distant. Avec --force-cp, le fichier est
systématiquement copié dans la destination.
-S, --ssh SSH -S, --ssh SSH
S'il faut classer sur un hôte distant avec scp, utiliser le programme S'il faut classer sur un hôte distant avec scp, utiliser le programme
spécifié pour la connexion par ssh spécifié pour la connexion par ssh
@ -108,6 +113,7 @@ args=(%
--help '$exit_with display_help' --help '$exit_with display_help'
-c:,--config: config= -c:,--config: config=
--file action=file --file action=file
--force-cp force_cp=1
-S:,--ssh: SSH= -S:,--ssh: SSH=
--force-scp force_scp=1 --force-scp force_scp=1
-n,--fake fake=1 -n,--fake fake=1
@ -251,7 +257,7 @@ for file in "$@"; do
} }
setx destdir=dirname -- "$dest" setx destdir=dirname -- "$dest"
docmd mkdir -p "$destdir" || die "$destdir: impossible de créer le répertoire" docmd mkdir -p "$destdir" || die "$destdir: impossible de créer le répertoire"
if [ $i -eq $mvi ]; then if [ $i -eq $mvi -a -z "$force_cp" ]; then
mvdesc="du déplacement" mvdesc="du déplacement"
mvcmd=mv mvcmd=mv
else else

16
ussh
View File

@ -343,15 +343,18 @@ function __update_sshopts_cm() {
version="$(ssh -V 2>&1)" version="$(ssh -V 2>&1)"
version="${version#OpenSSH_}"; major="${version%%.*}" version="${version#OpenSSH_}"; major="${version%%.*}"
minor="${version#$major.}"; minor="${minor:0:1}" minor="${version#$major.}"; minor="${minor:0:1}"
if [ $major -ge 6 ]; then if [ -z "$major" ]; then
# ne devrait pas se produire... mais au cas où
persist=
elif [ "$major" -ge 6 ]; then
persist="$DEFAULT_PERSIST" persist="$DEFAULT_PERSIST"
elif [ $major -eq 5 ]; then elif [ "$major" -eq 5 ]; then
if [ "$minor" -ge 6 ]; then if [ "$minor" -ge 6 ]; then
persist="$DEFAULT_PERSIST" persist="$DEFAULT_PERSIST"
else else
persist= persist=
fi fi
elif [ $major -le 4 ]; then elif [ "$major" -le 4 ]; then
persist= persist=
fi fi
fi fi
@ -383,7 +386,10 @@ function show_vars() {
function do_ssh() { function do_ssh() {
local -a sshopts local -a sshopts
local onehost r local onehost r
if [ "${#hosts[*]}" -gt 1 ]; then if [ ${#hosts[*]} -eq 0 -a $# -eq 0 ]; then
${exec:+exec} "$SSH" "${SSHOPTS[@]}"
return
elif [ "${#hosts[*]}" -gt 1 ]; then
onehost= onehost=
exec= exec=
else else
@ -447,7 +453,7 @@ if [ -n "$remove" ]; then
hosts=("$1"); shift hosts=("$1"); shift
fix_hosts fix_hosts
remove_keys remove_keys
else elif [ -n "$1" ]; then
hosts=("$1"); shift hosts=("$1"); shift
fix_hosts fix_hosts
fi fi