Category: Informatique

Migration de Drupal vers Wordpress terminée

Par kyusan, 11 janvier 2010 18 h 30 min

Le blog est passé de Drupal à Wordpress, pourquoi ce changement ? Après mon enthousiasme pour Drupal, j’ai fini par être lassé par les multiples mises à jour de sécurité et de perdre enormement de temps pour la mise à jour des plugins.

Poursuivre la lecture 'Migration de Drupal vers Wordpress terminée'»

perl completion in vim: i finally try it

Par mc, 10 novembre 2009 1 h 20 min

I was waiting a long time to have a perl completion system in vim. I waited because i’m lazy and because i thought someone more skilled than me will finally handle that. I don’t know about PPI or other perl parsing technics and i expected the completion to be really smart.

Time passed and there is no such thing in the place. I used ctags completion but it’s very borring to see packages names of your whole @INC when you try to complete a method name.

Still waiting for something really smart, i spent 2 evenings to write a ‘not so smart completion’ … my first use cases surprised me is it seems to be smart enought to go on waiting for another long time :-) .

I’ll try a daily use starting tomorrow and will feedback in a week. If you can’t wait for testing, debugging, feedback:

the perlcfu git repo

monger frustration …

Par mc, 27 août 2009 9 h 12 min

Perl is the first real language i used (i learnt to program with pascal and C but my first daily use programs where in perl), that’s right … But it’s wrong i sticked on perl « just because i know it »: I honnestly gave a try to python, ruby, php, lua, i’m abble to write code in C, C++, i read haskell, erlang or java codes.

I Finally sticked on perl after a long time of experiment (and i know that my next langages would be haskell and perl6) because i’m happy to see how it’s possible to write short and readable code when you know perl concepts and rules.

sub clear_session { (shift)->clear[qw< foo bar bang bing >] }
 
$_=2 for my ($a,$b,$c,$d);
 
sub trim_lr { s/ ^ \s* | \s* $ //xg } 
trim_lr for values %author;
 
sub commented_line { / ^ \s* # / }
 
my @lines = do {
    my $filename = 'foo.pl';
    open my $fh,$filename or die "can't open $filename: $!";
    map {
	if (commented_line) { () }
	else { "$. :".uc }
    }
};

… but now … i write code for a big OSS project with tons of lines of code and i realize that all those knowledges are useless because coworkers want you to write « more explicitly » and even the PBP tells you to use the « return » keyword.

sub clear_session { (shift)->clear[qw< foo bar bang bing >] }

becomes

sub clear_session {
    my $session    = shift;
    my @attributes = ( 'foo', 'bar', 'bang', 'bing' );
    return $session->clear(@attributes);
}

Yeah … i trully understand my coworkers because i remember, years ago, i had a poke on those kind of lines before understanding them and want to learn how to write them. I thought for years that the only thing that people missed to love perl is « understanding ». I realize i was wrong: lot of them just don’t like to be concise: they don’t want to understand and they are perfectly right in their point of view.

Now is the day i give up (in koha at least) fighting for spreading perl skills no one care about. A poor (and autoproclamed more readable) perl subset exists: it’s called python … and i’m wondering why i spent so much time to become a monger.

add js behaviors to koha

Par mc, 26 août 2009 15 h 36 min

when you create a new js file, you put it in the

koha-tmpl/WHERE-tmpl/prog/en/js/foo.js
# WHERE can be intranet or opac

now, in your template:

<script type="text/javascript" src="koha-tmpl/WHERE-tmpl/prog/en/js/foo.js"></script>

will fail if you use a translation. so write:

<script type="text/javascript" src="<!-- TMPL_VAR NAME='themelang' -->/js/behaviors.js"></script>

themelang is added in template C4::Output::gettemplate function (as you can easily see in the documentation) ;)

unix philosophy in the librarian culture ?

Par mc, 18 août 2009 10 h 38 min

I used and read a lot of tools since i’m at biblibre. One thing that surprised me is that lot of them completly ignore the unix philosophy. Most of them tries to make too many things in a monolithic code and aren’t usable as filter (my first concern is about the koha bulkmarcimport.pl).

I wonder if this philosophy get lost or has ever existed in the librarian culture? please feedback.

we badly need generic tools for marc manipulations

Par mc, 18 août 2009 9 h 51 min

hdl sent this link to me: a tool that make basic translations between marc fields (as copy, move, …). It reminds me my attempt to write a marcawk in which i tied MARC records in hashes.

the ed summer’s tool is very easy to use:

subjmap --translate=650ab

in marawk:

marawk -each '
    @{$_{650}{qw<a b>}} = @{$_{650}{qw<b a>}};
    print $_->as_usmarc;
'

in counterpart: my tool is more powerfull. The ultimate goal was to write
those kind of code to generate html reports

marawk -MCGI=:standard \
    -begin 'print start_html("book list"), start_table;'
    -each 'print Tr( map td($_)
	, $_{210}{a} . $_{210}{b}
	, $_{200}{a}
    )'
    -end 'print end_table, end_html;'
 
'

everything works but the automatic tie of subfields as hash
(i just had no time to investigate). It can be worked around easily with my
recent MARC::Mapper: it’s easy to patch marawk to write:

marawk -as unimarc -MCGI=:standard \
    -begin 'print start_html("book list"), start_table;'
    -each 'print Tr( map td($_)
	, $_->title 
	, $_->author
    )'
    -end 'print end_table, end_html;'

let’s get firefox out …

Par mc, 18 août 2009 8 h 31 min

My firefox keep going slow day by day. When loosing my nerves, i’m switching to safari (on my wife’s mac), adora and midori. I read this Emile’s post and consider testing chrome ASAP.

a MARC mapper in few lines of perl

Par mc, 6 août 2009 22 h 13 min

I spent this week migrating the legacy customer data from an old ILS to koha. This is a very funny job because you deal with a lot of data that interact each others. It’s not a collaborative work so you’re on your own to do this.

But there is a dumb part: the MARC format (a format used by libraries since decades for data exchanges). In MARC format, you can’t write

my @barcodes = $self->barcode;

but

map { $_->subfield('h') } $self->field('995');

You may think that it would be easy create an abstraction layer

sub barcodes { 
    map { $_->subfield('h') } (shift)->field('995');
}

But guess what? ‘h’ and ‘995′ depends to the standard you’re dealing with (USMARC,UNIMARC,…) and the local conventions of your ILS. So noone wrote an useless abstraction library. As data migrations are one shots code, it’s borring to write a complete abstraction for your specific case.

Hey! perl is a dynamic langage so it can write it for me: giving a field and a subfield, i can write closures:

sub create_closure { 
    my ($field,$subfield) = @_;
    sub { map { $_->subfield($subfield) } (shift)->field($field); }
};
 
my $get_barecodes = create_closure(qw< 995 a >);
say for $get_barecodes($record);

now i want this closure available as a function of your namespace. rgs++ gimme the solution:

*barcodes = $closure;
# or 
my $function_name = 'barcodes';
my $function_name_in_foo = 'Foo::barcodes';
*{$function_name} = $closure;
*{$function_name_in_foo} = $closure;

so now, what i need is just a hash that contains the name of the functions as keys and the field/subfields as values.

our %map = (
    item_barcode => [qw<995 h>]
    , isbn       => [qw<200 a>]
);

this is my complete and usable code. I’ll use it tomorrow to make my code easier to debug (yeah … still have bugs on my migration) but i still now there are tons of usages possible behind it.

#! /usr/bin/perl
use 5.10.0;
use utf8;
use strict;
use warnings;
use YAML;
 
package MARC::Mapper;
no strict;
 
sub create {
    my ($map) = @_;
    while( my ($function_name, $mapping) = each %$map ) {
	my $closure = sub {
	    my ($self) = shift || $_;
	    my $ref = ref $self;
	    if ($ref eq 'MARC::Field') {
		$self->subfield($$mapping[1])
	    } elsif ($ref eq 'MARC::Record') {
		map $_->subfield(
		    $$mapping[1]), $self->field($$mapping[0]
		);
	    }
	};
	*{$function_name} = $closure;
	my $export = (caller)[0]."::$function_name";
	*{$export} = $closure;
    }
}
 
use strict;
package main; 
use Test::More 'no_plan';
use MARC::Record;
 
my $r =  MARC::Record->new;
$r->append_fields( MARC::Field->new(995,('')x2, h => 'pouet'  ));
 
our %map = (
    item_barcode => [qw<995 h>]
);
 
my $expected = 'pouet';
MARC::Mapper::create(\%map);
 
is( $expected, (MARC::Mapper::item_barcode($r))[0], 'from MAPPER with record'); 
is( $expected, (item_barcode($r))[0], 'from main with record');
$_ = $r;
is( $expected, (item_barcode())[0], 'with $_ and record');
 
my $f = $r->field('995');
 
is( $expected, (MARC::Mapper::item_barcode($f))[0], 'from MAPPER with field'); 
is( $expected, (item_barcode($f))[0], 'from main with field');
$_ = $f;
is( $expected, (item_barcode())[0], 'with $_ and field');

put regexes in a module

Par mc, 27 juin 2009 17 h 37 min

Koha is full of complex regexes and the authors never used the x flag, this is one of the things i would like to rewrite. I want them to be readable, flexible, testable and documented … i want them in a module … so this is my draft. Feedbacks are welcome.

#! /usr/bin/perl
package Token::Archive; 
use strict;
use warnings;
use utf8;
 
=head1 Token::Archive 
 
matches the different parts of a CPAN archive filename.
 
this documentation uses the filename modifiers as you can find it in vim, csh
or zsh so if you're familiar to them, it would be easy to read this doc.
 
=head2 C<$basename>
 
just matches the basename ( :t ).  Note that you have to add the $ yourself
 
=cut
our $basename = qr{ [^/]+ }x;
 
 
=head2 C<$capture_basename>
 
capture the basename. 
 
... rest of the doc have to be written ...
=cut
 
our $capture_basename = qr{ ( $basename ) $ }x;
 
# capture one of the known extensions
our $extension = qr{
	\. (?:
	    tar.gz | tgz
	) 
}x;
 
# capture the basename 
our $capture_basename_without_extension = qr{
    ( $basename  )
    (?: $extension )
    $ 
}x;
our $capture_parts = qr{
    ( .* ) / 
    ( $basename )
    ( $extension )
    $ 
}x;

so now … it’s easy to use and test:

package main;
use utf8;
use strict;
use warnings;
use Token::Archive; 
use Test::More 'no_plan';
use Data::Compare;
use YAML;
 
sub test_token {
 
    # $description is the description of the test 
    # $result   is a ref to a ARRAY that contains submatches 
    # $expected is a ref to a ARRAY that contains what must be captured
    my ( $description, $result, $expected ) = @_;
    ok( Compare( $result, $expected )
	, $description  
    ) or diag( Dump $result ); 
};
 
 
$_="path/to/archive.tgz";
 
test_token 'the 3 parts are correct'
    , [/$Token::Archive::capture_parts/]
    , [qw< path/to archive .tgz >]
; 
 
test_token 'good basename'
    , [/$Token::Archive::capture_basename/]
    , [qw< archive.tgz >]
; 
 
test_token 'good basename without extension'
    , [/$Token::Archive::capture_basename_without_extension/]
    , [qw< archive >]
;

et voila …

ok 1 - the 3 parts are correct
ok 2 - good basename
ok 3 - good basename without extension
1..3

the counterpart is that every regexes are compiled …

mozilla jetpack

Par mc, 26 mai 2009 8 h 16 min

« come get some !!! » used to say Duke Nukem

https://jetpack.mozillalabs.com

Firefox is an unstable and ressource consuming browser and that’s right that i regulary try to find an alternative but i have to admit that the mozilla fundation shows the way of the web since netscape’s navigator code release …

Panorama Theme by Themocracy