From: olivier Date: Tue, 17 Jun 2008 14:37:42 +0000 (+0000) Subject: adding trunk and tags directories, moving files into trunk X-Git-Url: https://git.parisson.com/?a=commitdiff_plain;h=9f59f6571cc12b22e1bc02931ee14b227ce05105;p=telemeta-data.git adding trunk and tags directories, moving files into trunk git-svn-id: http://svn.parisson.org/svn/crem@37 3bf09e05-f825-4182-b9bc-eedd7160adf0 --- diff --git a/docref/crem.sql b/docref/crem.sql deleted file mode 100644 index 4f60c51..0000000 --- a/docref/crem.sql +++ /dev/null @@ -1,378 +0,0 @@ --- --- Copyright Samalyse SARL, 2008 --- Auteur: Olivier Guilyardi --- --- Structure de la nouvelle base du CREM --- --- Ce logiciel est régi par la licence CeCILL soumise au droit français et --- respectant les principes de diffusion des logiciels libres. Vous pouvez --- utiliser, modifier et/ou redistribuer ce programme sous les conditions --- de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA --- sur le site "http://www.cecill.info". --- --- En contrepartie de l'accessibilité au code source et des droits de copie, --- de modification et de redistribution accordés par cette licence, il n'est --- offert aux utilisateurs qu'une garantie limitée. Pour les mêmes raisons, --- seule une responsabilité restreinte pèse sur l'auteur du programme, le --- titulaire des droits patrimoniaux et les concédants successifs. --- --- A cet égard l'attention de l'utilisateur est attirée sur les risques --- associés au chargement, à l'utilisation, à la modification et/ou au --- développement et à la reproduction du logiciel par l'utilisateur étant --- donné sa spécificité de logiciel libre, qui peut le rendre complexe à --- manipuler et qui le réserve donc à des développeurs et des professionnels --- avertis possédant des connaissances informatiques approfondies. Les --- utilisateurs sont donc invités à charger et tester l'adéquation du --- logiciel à leurs besoins dans des conditions permettant d'assurer la --- sécurité de leurs systèmes et ou de leurs données et, plus généralement, --- à l'utiliser et l'exploiter dans les mêmes conditions de sécurité. --- --- Le fait que vous puissiez accéder à cet en-tête signifie que vous avez --- pris connaissance de la licence CeCILL, et que vous en avez accepté les --- termes. --- --- SVN:$Id$ --- - --- --- Enumérations simples --- - -CREATE TABLE physical_formats ( - id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, - value VARCHAR(250) NOT NULL -); - -CREATE TABLE publishing_status ( - id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, - value VARCHAR(250) NOT NULL -); - -CREATE TABLE acquisition_modes ( - id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, - value VARCHAR(250) NOT NULL -); - -CREATE TABLE metadata_authors ( - id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, - value VARCHAR(250) NOT NULL -); - -CREATE TABLE metadata_writers ( - id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, - value VARCHAR(250) NOT NULL -); - -CREATE TABLE legal_rights ( - id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, - value VARCHAR(250) NOT NULL -); - -CREATE TABLE recording_contexts ( - id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, - value VARCHAR(250) NOT NULL -); - -CREATE TABLE ad_conversions ( - id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, - value VARCHAR(250) NOT NULL -); - -CREATE TABLE vernacular_styles ( - id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, - value VARCHAR(250) NOT NULL -); - -CREATE TABLE generic_styles ( - id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, - value VARCHAR(250) NOT NULL -); - --- --- Editeurs et collections --- - -CREATE TABLE publishers ( - id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, - value VARCHAR(250) NOT NULL -); - -CREATE TABLE publisher_collections ( - id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, - publisher_id INTEGER NOT NULL, - value VARCHAR(250) NOT NULL, - - FOREIGN KEY(publisher_id) REFERENCES publishers (id) -); - --- --- Thésaurus géographique --- - -CREATE TABLE location_types ( - id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, - type VARCHAR(250) NOT NULL -); - -CREATE TABLE locations ( - name VARCHAR(250) NOT NULL PRIMARY KEY, - type ENUM('country', 'continent', 'other'), - complete_type_id INTEGER NOT NULL, - current_name VARCHAR(250), - is_authoritative BOOLEAN NOT NULL, - - FOREIGN KEY(current_name) REFERENCES locations (name), - FOREIGN KEY(complete_type_id) REFERENCES location_types (id) -); - -CREATE TABLE location_aliases ( - location_name VARCHAR(250) NOT NULL, - alias VARCHAR(250) NOT NULL, - is_authoritative BOOLEAN NOT NULL, - - PRIMARY KEY(location_name, alias), - FOREIGN KEY(location_name) REFERENCES locations (name) -); - -CREATE TABLE location_relations ( - location_name VARCHAR(250) NOT NULL, - parent_location_name VARCHAR(250) NOT NULL, - - PRIMARY KEY(location_name, parent_location_name), - FOREIGN KEY(location_name) REFERENCES locations (name), - FOREIGN KEY(parent_location_name) REFERENCES locations (name) -); - --- --- Ethnies --- - -CREATE TABLE ethnic_groups ( - id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, - name VARCHAR(250) NOT NULL -); - -CREATE TABLE ethnic_group_aliases ( - ethnic_group_id INTEGER NOT NULL, - name VARCHAR(250) NOT NULL, - - FOREIGN KEY(ethnic_group_id) REFERENCES ethnic_groups (id) -); - --- --- Collections --- - -CREATE TABLE media_collections ( - id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, - reference VARCHAR(250) NOT NULL UNIQUE, - physical_format_id INTEGER NOT NULL, - old_code VARCHAR(250) NOT NULL UNIQUE, - code VARCHAR(250) NOT NULL UNIQUE, - title VARCHAR(250) NOT NULL, - alt_title VARCHAR(250) NOT NULL, - physical_items_num INTEGER NOT NULL, - publishing_status_id INTEGER NOT NULL, - creator VARCHAR(250) NOT NULL, - booklet_author VARCHAR(250) NOT NULL, - booklet_description TEXT NOT NULL, - collector VARCHAR(250) NOT NULL, - collector_is_creator BOOLEAN NOT NULL, - publisher_id INTEGER NOT NULL, - year_published INTEGER NOT NULL, - publisher_collection_id INTEGER NOT NULL, - publisher_serial VARCHAR(250) NOT NULL, - external_references TEXT NOT NULL, - acquisition_mode_id INTEGER NOT NULL, - comment TEXT NOT NULL, - metadata_author_id INTEGER NOT NULL, - metadata_writer_id INTEGER NOT NULL, - legal_rights_id INTEGER NOT NULL, - alt_ids VARCHAR(250) NOT NULL, - recorded_from_year INTEGER NOT NULL, - recorded_to_year INTEGER NOT NULL, - recording_context_id INTEGER NOT NULL, - approx_duration TIME NOT NULL, - doctype_code INTEGER NOT NULL, - travail VARCHAR(250) NOT NULL, - state VARCHAR(250) NOT NULL, - cnrs_contributor VARCHAR(250) NOT NULL, - items_done VARCHAR(250) NOT NULL, - a_informer_07_03 VARCHAR(250) NOT NULL, - ad_conversion_id INTEGER NOT NULL, - public_access ENUM('none', 'metadata', 'full') NOT NULL, - - FOREIGN KEY(ad_conversion_id) REFERENCES ad_conversions (id), - FOREIGN KEY(publisher_collection_id) REFERENCES publisher_collections (id), - FOREIGN KEY(recording_context_id) REFERENCES recording_contexts (id), - FOREIGN KEY(publisher_id) REFERENCES publishers (id), - FOREIGN KEY(metadata_author_id) REFERENCES metadata_authors (id), - FOREIGN KEY(physical_format_id) REFERENCES physical_formats (id), - FOREIGN KEY(metadata_writer_id) REFERENCES metadata_writers (id), - FOREIGN KEY(legal_rights_id) REFERENCES legal_rights (id), - FOREIGN KEY(acquisition_mode_id) REFERENCES acquisition_modes (id), - FOREIGN KEY(publishing_status_id) REFERENCES publishing_status (id) -); - --- --- Items --- - -CREATE TABLE media_items ( - id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, - collection_id INTEGER NOT NULL, - track VARCHAR(250) NOT NULL, - code VARCHAR(250) NOT NULL, - approx_duration TIME NOT NULL, - recorded_from_date DATE NOT NULL, - recorded_to_date DATE NOT NULL, - location_name VARCHAR(250) NOT NULL, - location_comment VARCHAR(250) NOT NULL, - ethnic_group_id INTEGER NOT NULL, - title VARCHAR(250) NOT NULL, - alt_title VARCHAR(250) NOT NULL, - author VARCHAR(250) NOT NULL, - vernacular_style_id INTEGER NOT NULL, - context_comment TEXT NOT NULL, - external_references VARCHAR(250) NOT NULL, - moda_execut VARCHAR(250) NOT NULL, - copied_from_item_id INTEGER, - collector VARCHAR(250) NOT NULL, - cultural_area VARCHAR(250) NOT NULL, - generic_style_id INTEGER NOT NULL, - collector_selection VARCHAR(250) NOT NULL, - creator_reference VARCHAR(250) NOT NULL, - filename VARCHAR(250) NOT NULL, - public_access ENUM('none', 'metadata', 'full') NOT NULL, - - FOREIGN KEY(ethnic_group_id) REFERENCES ethnic_groups (id), - FOREIGN KEY(collection_id) REFERENCES media_collections (id), - FOREIGN KEY(vernacular_style_id) REFERENCES vernacular_styles (id), - FOREIGN KEY(location_name) REFERENCES locations (name), - FOREIGN KEY(copied_from_item_id) REFERENCES media_items (id), - FOREIGN KEY(generic_style_id) REFERENCES generic_styles (id) -); - --- --- Parties d'item/marqueurs --- - -CREATE TABLE media_parts ( - id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, - item_id INTEGER NOT NULL, - title VARCHAR(250) NOT NULL, - start FLOAT NOT NULL, - end FLOAT NOT NULL, - - FOREIGN KEY(item_id) REFERENCES media_items (id) -); - --- --- Instruments et formations --- - -CREATE TABLE instruments ( - id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, - name VARCHAR(250) NOT NULL -); - -CREATE TABLE instrument_relations ( - instrument_id INTEGER NOT NULL, - parent_instrument_id INTEGER NOT NULL, - - FOREIGN KEY(instrument_id) REFERENCES instruments (id), - FOREIGN KEY(parent_instrument_id) REFERENCES instruments (id) -); - -CREATE TABLE instrument_aliases ( - id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, - name VARCHAR(250) NOT NULL -); - -CREATE TABLE instrument_alias_relations ( - alias_id INTEGER NOT NULL, - instrument_id INTEGER NOT NULL, - - FOREIGN KEY(alias_id) REFERENCES instrument_aliases (id), - FOREIGN KEY(instrument_id) REFERENCES instruments (id) -); - -CREATE TABLE media_item_performances ( - media_item_id INTEGER NOT NULL, - instrument_id INTEGER NOT NULL, - alias_id INTEGER NOT NULL, - instruments_num VARCHAR(250) NOT NULL, - musicians VARCHAR(250) NOT NULL, - - FOREIGN KEY(media_item_id) REFERENCES media_items (id), - FOREIGN KEY(instrument_id) REFERENCES instruments (id), - FOREIGN KEY(alias_id) REFERENCES instrument_aliases (id) -); - --- --- Contexte ethnographique --- - -CREATE TABLE context_keywords ( - id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, - value VARCHAR(250) NOT NULL -); - -CREATE TABLE media_item_keywords ( - item_id INTEGER NOT NULL, - keyword_id INTEGER NOT NULL, - - PRIMARY KEY(item_id, keyword_id), - FOREIGN KEY(item_id) REFERENCES media_items (id), - FOREIGN KEY(keyword_id) REFERENCES context_keywords (id) -); - --- --- Utilisateurs --- - -CREATE TABLE users ( - username VARCHAR(64) NOT NULL PRIMARY KEY, - level ENUM ('user', 'maintainer', 'admin') NOT NULL, - first_name VARCHAR(250) NOT NULL, - last_name VARCHAR(250) NOT NULL, - phone VARCHAR(250) NOT NULL, - email VARCHAR(250) NOT NULL -); - --- --- Séléctions --- - -CREATE TABLE playlists ( - id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, - owner_username VARCHAR(250) NOT NULL, - name VARCHAR(250) NOT NULL, - - FOREIGN KEY(owner_username) REFERENCES users (username) -); - -CREATE TABLE playlist_resources ( - playlist_id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, - resource_type ENUM('item', 'collection') NOT NULL, - resource_id INTEGER NOT NULL, - - FOREIGN KEY(playlist_id) REFERENCES playlists (id) -); - - --- --- Historique des modifications --- - -CREATE TABLE revisions ( - id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, - element_type VARCHAR(32) NOT NULL, - element_id INTEGER NOT NULL, - change_type ENUM('create', 'update', 'delete') NOT NULL, - time DATETIME NOT NULL, - username VARCHAR(64) NOT NULL, - - FOREIGN KEY(username) REFERENCES users (username) -); - diff --git a/docref/crem.zargo b/docref/crem.zargo deleted file mode 100644 index 4f7b7e8..0000000 Binary files a/docref/crem.zargo and /dev/null differ diff --git a/docref/docref-0.1-prealpha.odt b/docref/docref-0.1-prealpha.odt deleted file mode 100644 index 4c8a8df..0000000 Binary files a/docref/docref-0.1-prealpha.odt and /dev/null differ diff --git a/docref/docref-0.2-prealpha.odt b/docref/docref-0.2-prealpha.odt deleted file mode 100644 index 79cba1f..0000000 Binary files a/docref/docref-0.2-prealpha.odt and /dev/null differ diff --git a/docref/docref-0.3-alpha.odt b/docref/docref-0.3-alpha.odt deleted file mode 100644 index 4295755..0000000 Binary files a/docref/docref-0.3-alpha.odt and /dev/null differ diff --git a/docref/docref-0.4-beta.odt b/docref/docref-0.4-beta.odt deleted file mode 100644 index f043e96..0000000 Binary files a/docref/docref-0.4-beta.odt and /dev/null differ diff --git a/docref/docref.odt b/docref/docref.odt deleted file mode 100644 index 5e96532..0000000 Binary files a/docref/docref.odt and /dev/null differ diff --git a/docref/spec/build.sh b/docref/spec/build.sh deleted file mode 100644 index 14af7e3..0000000 --- a/docref/spec/build.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash - -python parse.py -cd build -rst2html docref.txt docref.html && rst2latex docref.txt docref.tex && pdflatex docref.tex - diff --git a/docref/spec/docref.txt b/docref/spec/docref.txt deleted file mode 100644 index 48bb608..0000000 --- a/docref/spec/docref.txt +++ /dev/null @@ -1,223 +0,0 @@ - - -=================================================================== -Recommandations pour la réorganisation de la base de donnée du CREM -=================================================================== ------------------------------------- -Document de référence, version alpha ------------------------------------- - - -I - Enjeux -========== - -I.1 - Recherche d'informations ------------------------------- - -L'analyse de la structure de données et la rencontre des personnes concernées par son usage -permettent de délimiter des enjeux majeurs. Il apparaît notamment que le fond documentaire -que constitue cette base n'est actuellement pas mis à profit comme il pourrait l'être. Cette -base est largement sous-utilisée, les chercheurs, pour certains, ne l'utilisent pas du tout. - -La raison principale de cette situation est le fait que l'environnement technique et la -structure de la base ont été conçus pour s'inscrire dans un environnement documentaire -traditionnel, qui implique généralement de prendre contact avec un documentaliste pour effectuer -une recherche. Le documentaliste est un spécialiste de la base, il possède les connaissances -techniques nécessaires à sa consultation. - -Mais à l'heure d'Internet, ce processus de recherche est trop lourd et inadapté, en un mot -: obsolète. Les chercheurs lui préfèrent d'autres fonds documentaires accessibles en ligne, -de façon immédiate, et équipés d'outils de recherche puissants et ergonomiques. - -L'enjeu principal de la réorganisation de la base du CREM consiste donc à : sous-tendre le -développement d'un outil moderne de gestion et de consultation en ligne, avec des fonctions -de recherche puissantes et intuitives déterminer et améliorer les données de la base qui -sont prioritaires pour la recherche d'information - -En de-ça des-dits champs prioritaires, il existe un grand nombre d'information techniques de -second ordre, qui soit ne sont utiles qu'aux documentalistes, soit ne présentent pas d'intérêt -majeur pour la recherche d'information. Ces informations peuvent être conservées telles quelles, -sans grand effort de réorganisation, et resteront ainsi disponibles lors de la consultation -individuelle des fiches. - -En procédant de cette façon, c'est à dire en délimitant les-dîtes priorités, il semble -possible de dégager une véritable plus-value, de rendre le fond documentaire du CREM plus vivant, -sans pour autant engager des moyens démesurés dans la réorganisation de la base de donnée. - -I.2 - Gestion et mise à jour des données ----------------------------------------- - -Il est entendu qu'au delà de la consultation d'information, il s'agit également de faciliter -la gestion des données, leur mise à jour. Cette question implique pour une large part des -problématiques d'ordre ergonomique, liées au développement d'un outil logiciel autour de la -base, ce qui n'entre pas dans le cadre de la réorganisation de la base de données. - -Cependant, au niveau de la base, certains choix sont structurant. Par exemple l'emploi d'une -liste hiérarchisée de lieux telle que le Thesaurus of Geographical Names (TGN, recommandé par -Dublin Core), permet, en choisissant une région, une sous-région ou un village, de renseigner -automatiquement le pays (et les autres zones géographiques intermédiaires), ce qui diminue -l'effort et prévient les erreurs de saisie. - -Pour un grand nombre de champs, l'emploi d'énumérations (liste de valeurs valides pour -un champ donné) facilite et valide déjà la mise à jour des données. Cet aspect de la base -devra être conservé. - -Cependant, il semble que l'enjeu majeur de la réorganisation, du point de vue de la gestion -des données, est de permettre un travail collaboratif, entre chercheurs et documentalistes. C'est -là, d'une manière générale, ce qui permet sur Internet de rendre un fond documentaire vivant. - -Dans le cadre du CREM, il serait ainsi idéal d'amener les chercheurs à alimenter la base de -façon autonome, en sus des documentalistes dont c'est le métier. Ce serait là une véritable -nouveauté, représentant un fort potentiel d'enrichissement des données. - -D'une façon générale, une application en ligne ("webifiée") bien conçue se prête -très bien au travail collaboratif. Cependant, il semble que dans notre cas, les potentielles -contributions des chercheurs se heurtent à une question importante de confidentialité et -de propriété intellectuelle. Des cas ont en effet été rapportés d'usage détournés du -fruit du travail du centre de recherche, et d'une manière générale, il semble qu'il faille -observer une grande prudence pour la mise en commun d'enregistrement sonores et autres données, -qui représentent une matière précieuse aux yeux des chercheurs. - -La sécurité informatique est pour une large part distinct de la base de donnée ; elle -implique des efforts particuliers au niveau du développement applicatif, et de l'administration -de l'infrastructure réseau. - -Cependant, au niveau de la base de donnée, il est possible de mettre l'accent sur la -propriété des données. Chaque ressource (collection, item) peut en effet se voir attribuer -un propriétaire. Le dit propriétaire devrait ensuite pouvoir choisir quel autre utilisateur -et/ou groupe d'utilisateur est autorisé à consulter, écouter, et/ou modifier la ressource. - -En rassurant ainsi les chercheurs, il est envisageable que la base s'enrichisse notablement -par leurs contributions, dont certaines d'abord privées, pourront, à leur guise, devenir -petit à petit accessibles à un nombre grandissant d'utilisateurs et de groupes de travail. - -I.3 - Données prioritaires - -Après consultation des différents utilisateurs il apparaît que les meta-données principales -pour chaque item sont : - -* l'identifiant unique de l'item -* le titre de l'item -* la zone géographique -* le nom du collecteur, c'est à dire le chercheur qui a collecté cet enregistrement -* les instruments de musique utilisés -* l'année d'enregistrement -* le contexte ethnographique -* l'ethnie - -Il s'agit d'apporter une attention particulière à celles-ci, notamment en les normalisant, -pour faciliter la recherche d'informations, mais aussi pour l'ajout et la gestion simplifiés -d'items. - -Les autres données pourront être conservées telles quelles sans grand effort de normalisation. - -I.4 - Dublin Core ------------------ - -... - -II - Modalités de conversion/réorganisation de la base -====================================================== - -II.1 - Enumérations simples ---------------------------- - -dynamic:tables.describe_enums() - -II.2 - Collections ------------------- - -Ancien nom de table : support - -Nouveau nom de table : media_collections - -II.2.1 - Champs convertis -~~~~~~~~~~~~~~~~~~~~~~~~~ - -dynamic:tables.media_collections.describe_conversion() - -II.2.2 - Nouveaux champs -~~~~~~~~~~~~~~~~~~~~~~~~ - -dynamic:tables.media_collections.describe_new_fields() - -II.2.3 - Champs supprimés -~~~~~~~~~~~~~~~~~~~~~~~~~ - -dynamic:tables.media_collections.describe_removed_fields() - -II.3 - Items ------------- - -Ancien nom de table : phono - -Nouveau nom de table : media_items - -II.3.1 - Champs convertis -~~~~~~~~~~~~~~~~~~~~~~~~~ - -dynamic:tables.media_items.describe_conversion() - -II.3.2 - Nouveaux champs -~~~~~~~~~~~~~~~~~~~~~~~~ - -dynamic:tables.media_items.describe_new_fields() - -II.3.3 - Champs supprimés -~~~~~~~~~~~~~~~~~~~~~~~~~ - -dynamic:tables.media_items.describe_removed_fields() - -II.4 - Sélections ------------------ - -II.4.1 - Liste -~~~~~~~~~~~~~~ - -Nom de table: -dynamic:tables.media_playlists.name - -dynamic:tables.media_playlists.describe_new_fields() - -II.4.2 - Table de relation interne -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Nom de table: -dynamic:tables.media_playlist_resources.name - -dynamic:tables.media_playlist_resources.describe_new_fields() - -II.5 - Thesaurus Géographique ------------------------------ - -II.5.1 - Lieux -~~~~~~~~~~~~~~ - -Nom de table: -dynamic:tables.locations.name - -dynamic:tables.locations.describe_new_fields() - -II.5.2 - Alias des lieux -~~~~~~~~~~~~~~~~~~~~~~~~ - -Nom de table: -dynamic:tables.location_aliases.name - -dynamic:tables.location_aliases.describe_new_fields() - -II.5.3 - Relations hiérarchiques -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Nom de table: -dynamic:tables.location_relations.name - -dynamic:tables.location_relations.describe_new_fields() - -II.6 - Utilisateurs -------------------- - -Nom de table: -dynamic:tables.users.name - -dynamic:tables.users.describe_new_fields() diff --git a/docref/spec/elements.py b/docref/spec/elements.py deleted file mode 100644 index e46b8d7..0000000 --- a/docref/spec/elements.py +++ /dev/null @@ -1,136 +0,0 @@ -#coding: utf-8 -import sqlalchemy -import texttable - -def make_table(rows, width=20): - return texttable.indent(rows, hasHeader = True, separateRows = True, - prefix=u'| ', postfix=u' |', - wrapfunc = lambda x: texttable.wrap_onspace(x, width=width)) - -def describe_enums(metadata): - rows = [['Nom interne', 'Ancien nom', 'Description']] - for enum in metadata.enums: - rows.append([enum.name, enum.old_name, enum.label]) - return make_table(rows, 40) - -class Column(sqlalchemy.Column): - old_name = '' - label = '' - desc = '' - dc = '' - comment = '' - conversion = '' - enum = None - - def __init__(self, name, type, *args, **kwargs): - parent_args = {} - for key, value in kwargs.items(): - if key == 'old_name': - if isinstance(value, list): - self.old_name = unicode(",\n".join(value), 'utf-8') - #self.old_name = [] - #for item in value: - # self.old_name.append(unicode(item, 'utf-8')) - else: - self.old_name = unicode(value, 'utf-8') - elif key == 'label': - self.label = unicode(value, 'utf-8') - elif key == 'desc': - self.desc = unicode(value, 'utf-8') - elif key == 'dc': - self.dc = value - elif key == 'comment': - self.comment = unicode(value, 'utf-8') - elif key == 'conversion': - self.conversion = unicode(value, 'utf-8') - else: - parent_args[key] = value - - if isinstance(type, Enumeration): - args = (sqlalchemy.ForeignKey(type.name + '.id'),) + args - self.enum = type - type = sqlalchemy.Integer - - super(Column, self).__init__(name, type, *args, **parent_args) - -class RemovedColumn(object): - old_name = '' - comment = '' - - def __init__(self, old_name, comment=''): - self.old_name = unicode(old_name, 'utf-8') - self.comment = unicode(comment, 'utf-8') - -class Table(sqlalchemy.Table): - - def __init__(self, table_name, metadata, label, *args): - self.label = unicode(label, 'utf-8') - real_columns = [] - self.removed_columns = [] - for column in args: - if isinstance(column, RemovedColumn): - self.removed_columns.append(column) - else: - real_columns.append(column) - super(Table, self).__init__(table_name, metadata, *real_columns) - - - def describe_new_fields(self): - rows = [['Nom', 'Nom interne', 'Dublin Core']] - for column in self.columns: - if not column.old_name: - rows.append([column.label, column.name, column.dc]) - - return make_table(rows) - - def describe_conversion(self): - rows = [['Nouveau nom', 'Ancien nom', 'Nouveau nom interne', 'Dublin Core']] - for column in self.columns: - if column.old_name: - rows.append([column.label, column.old_name, column.name, column.dc]) - - return make_table(rows) - - def describe_removed_fields(self): - rows = [['Nom', 'Commentaire']] - for column in self.removed_columns: - rows.append([column.old_name, column.comment]) - - return make_table(rows, 50) - - def to_dot(self): - dot = u'digraph g {\n' - dot += ' charset = "utf-8";\n' - dot += ' node [shape=record, charset="utf-8"];\n' - dot += ' rankdir = LR;\n' - dot += ' subgraph cluster_new_fields {\n' - dot += ' label = "Nouveaux champs";\n' - dot += ' color = black;\n' - old_fields = '' - conversion = '' - for column in self.columns: - dot += ' ' + column.name + '[label = "{' + column.label + ' | ' + column.name + '}"];\n' - if column.old_name: - old_fields += ' old_' + column.name + '[label = "' + column.old_name + '"];\n' - conversion += ' old_' + column.name + ' -> ' + column.name + ';\n' - dot += ' }\n' - dot += ' subgraph cluster_old_fields {\n' - dot += ' label = "Anciens champs";\n' - dot += ' color = black;\n' - dot += old_fields - dot += ' }\n' - dot += conversion - dot += '}\n' - return dot - -class Enumeration(Table): - - def __init__(self, name, metadata, label='', old_name=''): - self.old_name = unicode(old_name, 'utf-8') - if not hasattr(metadata, 'enums'): - metadata.enums = [] - metadata.enums.append(self) - super(Enumeration, self).__init__(name, metadata, label, - Column('id', sqlalchemy.Integer, primary_key=True), - Column('value', sqlalchemy.String(250), unique=True) - ) diff --git a/docref/spec/parse.py b/docref/spec/parse.py deleted file mode 100644 index 535832c..0000000 --- a/docref/spec/parse.py +++ /dev/null @@ -1,18 +0,0 @@ - -import tables -import codecs -input = codecs.open('docref.txt', 'r', "utf-8") -output = codecs.open('build/docref.txt', 'w', "iso-8859-1") - -for line in input: - if line[0:8] == 'dynamic:': - output.write(eval(line[8:], globals(), locals()) + "\n") - else: - output.write(line) - -input.close() -output.close() - -output = codecs.open('build/collections.dot', 'w', 'utf-8') -output.write(tables.media_collections.to_dot()) -output.close() diff --git a/docref/spec/staticenum.py b/docref/spec/staticenum.py deleted file mode 100644 index d364f5b..0000000 --- a/docref/spec/staticenum.py +++ /dev/null @@ -1,69 +0,0 @@ -#!python - -## The MIT License - -## Copyright (c) - -## Permission is hereby granted, free of charge, to any person obtaining a copy -## of this software and associated documentation files (the "Software"), to deal -## in the Software without restriction, including without limitation the rights -## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -## copies of the Software, and to permit persons to whom the Software is -## furnished to do so, subject to the following conditions: - -## The above copyright notice and this permission notice shall be included in -## all copies or substantial portions of the Software. - -## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -## THE SOFTWARE. - - -from sqlalchemy import types, exceptions - -class StaticEnum(types.TypeDecorator): - impl = types.Unicode - - def __init__(self, values, empty_to_none=False, strict=False): - """Emulate an Enum type. - - values: - A list of valid values for this column - empty_to_none: - Optional, treat the empty string '' as None - strict: - Also insist that columns read from the database are in the - list of valid values. Note that, with strict=True, you won't - be able to clean out bad data from the database through your - code. - """ - - if values is None or len(values) is 0: - raise exceptions.AssertionError('StaticEnum requires a list of values') - self.empty_to_none = empty_to_none - self.strict = strict - self.values = values[:] - - # The length of the string/unicode column should be the longest string - # in values - size = max([len(v) for v in values if v is not None]) - super(StaticEnum, self).__init__(size) - - - def convert_bind_param(self, value, engine): - if self.empty_to_none and value is '': - value = None - if value not in self.values: - raise exceptions.AssertionError('"%s" not in StaticEnum.values' % value) - return super(StaticEnum, self).convert_bind_param(value, engine) - - - def convert_result_value(self, value, engine): - if self.strict and value not in self.values: - raise exceptions.AssertionError('"%s" not in StaticEnum.values' % value) - return super(StaticEnum, self).convert_result_value(value, engine) - diff --git a/docref/spec/tables.py b/docref/spec/tables.py deleted file mode 100644 index 41fd6d4..0000000 --- a/docref/spec/tables.py +++ /dev/null @@ -1,331 +0,0 @@ -#coding: utf-8 - -import sqlalchemy -from sqlalchemy import String, Integer, ForeignKey, Time, Date, MetaData, Text, Boolean -from elements import Column, RemovedColumn, Table, Enumeration -import elements -from staticenum import StaticEnum - -metadata = MetaData() -def describe_enums(): - return elements.describe_enums(metadata) - -# Users - -users = Table('users', metadata, 'Utilisateurs', - Column('username', String(250), primary_key=True, label='Nom d\'utilisateur'), - Column('level', StaticEnum('user,maintainer,administrator'), label='Niveau de permissions'), - Column('first_name', String(250), label='Prénom'), - Column('last_name', String(250), label='Nom'), - Column('phone', String(250), label='Téléphone'), - Column('email', String(250), label='E-Mail') -) - -# Playlists - -media_playlists = Table('playlists', metadata, 'Sélections personelles d\'items et de collections', - Column('id', Integer, primary_key='true', label='Identifiant'), - Column('owner_username', String(250), ForeignKey('users.username'), label='Propriétaire'), - Column('name', String(250), label='Intitulé')) - -media_playlist_resources = Table('playlist_resources', metadata, 'Ressources associées aux sélections personelles ', - Column('playlist_id', Integer, ForeignKey('playlists.id'), label='Identifiant de la sélection'), - Column('resource_type', StaticEnum('item', 'collection'), label='Type de ressource (item, collection)'), - Column('resource_id', String(250), label='Identifiant de la ressource') -) - -# Simple enumerations - -physical_formats = Enumeration('physical_formats', metadata, 'Formats physiques', old_name='Format (e)') -publishing_status = Enumeration('publishing_status', metadata, 'Status d\'édition/réédition', old_name='Réédition (e)') -publishers = Enumeration('publishers', metadata, 'Editeurs', old_name='Editeur1 (e)') -acquisition_modes = Enumeration('acquisition_modes', metadata, 'Modes d\'acquisition', old_name='Mode_Acqui (e)') -metadata_authors = Enumeration('record_authors', metadata, 'Rédacteurs des fiches', old_name='Rédacteur_Fiche (e)') -metadata_writers = Enumeration('metadata_writers', metadata, 'Opérateur de saisie des fiches', old_name='Saisie_Fiche (e)') -legal_rights = Enumeration('legal_rights', metadata, 'Statuts juridiques', old_name='Droit_d\'Utiliser (e)') -recording_contexts = Enumeration('recording_contexts', metadata, 'Contextes d\'enregistrement', old_name='Terrain_ou_Autre (e)') -ad_conversions = Enumeration('ad_conversions', metadata, 'Statuts de numérisation', old_name='Numérisation (e)') -ethnic_groups = Enumeration('ethnic_groups', metadata, 'Ethnies/Groupe social', old_name='Ethnie (t)') -vernacular_styles = Enumeration('vernacular_styles', metadata, 'Forme / genre vernaculaire', old_name='Form (t)') -generic_styles = Enumeration('generic_styles', metadata, 'Forme / genre générique', old_name='FormStyle générique (e)') -context_keywords = Enumeration('context_keywords', metadata, 'Mots clés du contexte ethnographique', old_name='Mot_Clef (t)') -publisher_collections = Enumeration('publisher_collections', metadata, 'Collections éditeur', old_name='Collection_Série (e)') - -# Geographic Thesaurus - -location_types = Enumeration('location_types', metadata, 'GeoEthno / Types de lieux') - -locations = Table('locations', metadata, 'GeoEthno / Lieux)', - Column('name', String(127), primary_key=True, label='Terme descripteur'), - Column('type', StaticEnum('country', 'continent', 'other')), - Column('complete_type', location_types), - Column('current_name', String(127), ForeignKey('locations.name'), label='Nom actuel'), - Column('is_authoritative', Boolean), -) - -location_aliases = Table('location_aliases', metadata, 'GeoEthno / Alias des lieux', - Column('location_name', String(127), ForeignKey('locations.name'), primary_key=True), - Column('alias', String(127), primary_key=True), - Column('is_authoritative', Boolean)) - -location_relations = Table('location_relations', metadata, 'GeoEthno / Relations hiérachiques', - Column('location_name', String(127), ForeignKey('locations.name'), primary_key=True), - Column('parent_location_name', String(127), ForeignKey('locations.name'), primary_key=True) -) - -# Media Collections - -media_collections = Table('media_collections', metadata, 'Collections', - Column('reference', - String(250), unique=True, - old_name='Réf', label='Référence'), - Column('physical_format_id', - physical_formats, - old_name='Format', label='Format', - desc="Format du 1er exemplaire archivé"), - Column('old_id', - String(250), - old_name='Cote', label='Ancienne cote'), - Column('id', - String(250), primary_key=True, - dc='identifier', - label='Cote', conversion='à préciser'), - Column('title', - String(250), - dc='title', - old_name='Titre', label='Titre'), - Column('native_title', - String(250), - dc='title', - old_name='Transcrip_Trad', label='Traduction du titre'), - Column('physical_items_num', - Integer, - old_name='Nb_de_pieces', label='Nombre de supports physiques'), - Column('publishing_status_id', - publishing_status, - old_name='Réédition', label='Réédition'), - RemovedColumn(old_name='Original'), - RemovedColumn(old_name='Copie_TotPartie'), - RemovedColumn(old_name='Copié_de'), - Column('creator', - String(250), - dc='creator', - old_name='Auteur_Compil', label='Auteur / Cédant'), - Column('booklet_author', - String(250), - dc='contributor', - old_name='Auteur_Notice', label='Auteur notice'), - Column('booklet_description', - Text, - old_name='Notice', label='Notice / Dossier technique'), - Column('collector', - Text, - dc='contributor', - old_name='Collecteur', label='Collecteur'), - Column('publisher_id', - publishers, - dc='publisher', - old_name='Editeur', label='Editeur', - desc='Pour les documents ÉDITÉS:Nom et État de l\'Editeur. Pour les INÉDITS :voir champ "Type de document".'), - Column('year_published', - Integer, - dc='date', - old_name='Année_parution', label='Année de parution', - desc='Ne concerne que les documents ÉDITÉS.', - conversion='à préciser, traiter les nombres négatifs ?'), - Column('publisher_collection', - publisher_collections, - old_name='Collect_Série', label='Collection éditeur', - comment='faux: nom de la collection, suivi du n° dans la collection.'), - Column('publisher_serial', - String(250), - old_name='Num_Dans_Collec', label='Numéro de série', - desc='Numéro de série dans la collection éditeur', - comment='à valider'), - Column('external_references', - Text, - old_name='Réf_Biblio', label='Bibliographie', - desc='Références biblio/disco/filmographiques, uniquement liées à ce support'), - Column('acquisition_mode_id', - acquisition_modes, - old_name='Mod_Acqui', label='Mode d\'acquisition'), - Column('comment', - Text, - old_name='Commentaire', label='Commentaire'), - Column('metadata_author_id', - metadata_authors, - dc='contributor', - old_name='Rédacteur_Fiche', label='Rédacteur fiche', - desc='Responsable de l\'analyse documentaire'), - Column('metadata_writer_id', - metadata_writers, - old_name='Saisie_Fiche', label='Saisie fiches', - desc='Personne qui a saisi les fiches dans la base de données.'), - Column('legal_rights_id', - legal_rights, - dc='rights', - old_name='Droit_Utiliser', label='Statut juridique'), - Column('alt_ids', - String(250), - old_name='Autres_Cotes', label='Autres exemplaires'), - Column('recorded_from_year', - Integer, - dc='date', - old_name='Année_Enreg', label='Années d\'enregistrement', - conversion="split"), - Column('recorded_to_year', - Integer, - dc='date', - old_name='Année_Enreg', label='Années d\'enregistrement', - conversion="split"), - Column('recording_context_id', - recording_contexts, - old_name='Terrain_ou_Autr', label='Contexte d\'enregistrement'), - Column('approx_duration', - Time(), - old_name='Durée_approx', label='Durée approximative'), - Column('doctype_code', - Integer, - old_name='Tri_DiBm', label='Type de document'), - Column('travail', - String(250), - old_name='Travail', label='?'), - Column('state', - String(250), - old_name='Compil_Face_Plage', label="Etat"), - Column('cnrs_contributor', - String(250), - old_name='Déposant_CNRS', label="Déposant CNRS", - desc='Pour les INÉDITS uniquement. Signale les collectes ayant bénéficées d\'une aide du CNRS.'), - Column('items_done', - String(250), - old_name='Fiches', label='Fiches faîtes', - desc="Signale que les fiches Item de ce support sont présentes dans la base."), - Column('a_informer_07_03', - String(250), - old_name='A informer_07-03', label='?'), - Column('ad_conversion_id', - ad_conversions, - old_name='Numérisation', label="Historique de numérisation"), - RemovedColumn(old_name='Champ36'), -) - -# Media Items - -media_item_context_keywords = Table('media_item_context_keywords', metadata, - 'Mots clés associés à un item', - Column('media_item_id', Integer, ForeignKey('media_items.id')), - Column('context_keyword_id', context_keywords)) - -media_items = Table('media_items', metadata, 'Items', - RemovedColumn(old_name='Réf', comment='Calculé en temps réel à partir de la collection'), - Column('collection_id', - String(250), ForeignKey('media_collections.id'), - dc='relation/isPartOf', - label='Collection'), - RemovedColumn(old_name='Format', comment='Calculé en temps réel à partir de la collection'), - RemovedColumn(old_name='Cote_Support', comment='Calculé en temps réel à partir de la collection'), - Column('track', - String(250), - old_name="Face_Plage", label="N° de l'item"), - Column('id', - String(250), - old_name='Cote_Phono', label="Cote item"), - Column('approx_duration', - Time(), - old_name='Durée', label='Durée'), - Column('recorded_from_date', - Date(), - dc='date', - old_name='Date_enregistr', label='Date', desc='Date de l\'enregistrement'), - Column('recorded_to_date', - Date(), - dc='date', - old_name='Date_enregistr', label='Date'), - Column('location_name', - Integer, ForeignKey('locations.name'), - dc='coverage', - old_name=['Continent', 'Etat', 'Région_Village'], label='Lieu', - desc='(?) Lieu de provenance de la musique. Si le lieu de l\'enregistrement est autre, l\'indiquer en "Remarques".'), - Column('location_comment', - String(250), - old_name='Région_Village', label='Commentaire lieu'), - Column('ethnic_group_id', - ethnic_groups, - old_name='Ethnie_GrSocial', label='Ethnie/Groupe social', comment='attention alias ethnies'), - RemovedColumn(old_name='Titre_Support', comment='Calculé en temps réel à partir de la collection'), - Column('title', - String(250), - dc='title', - old_name='Titre_pièce', label='Titre Item'), - Column('native_title', - String(250), - dc='title', - old_name='Transcrip_Trad', label='Traduction du titre', - desc='Traduction des langues non communes, plus translittération des langues n\'utilisant pas l\'alphabet latin.'), - Column('author', - String(250), - dc='creator', - old_name='Auteur', label='Auteur', - desc='Le cas échéant, faire suivre le nom par une mention "-auteur /-compositeur / -arrangeur"'), - Column('vernacular_style_id', - vernacular_styles, - old_name='Form_Genr_Style', label='Forme / genre vernaculaire [nom à revoir]', - desc='Nom local de la forme ou du genre'), - RemovedColumn(old_name='Struct_Modale'), - RemovedColumn(old_name='Struct_Rythm'), - RemovedColumn(old_name='Struct_Rythm'), - RemovedColumn(old_name='Fonction_Usage', - comment='Champ inutile, les mots clés sont associés via une table de relation externe'), - Column('context_comment', - Text, - old_name='Comm_FonctUsage', label='Contexte ethnographique : commentaires'), - Column('external_references', - String(250), - old_name='Documentation', label='Références', - desc='Références directement liées à l\'item.'), - Column('moda_execut', - String(250), - old_name='Moda_Execut', comment='à supprimer ?'), - Column('copied_from_item_id', - String(250), ForeignKey('media_items.id'), - dc='relation/isVersionOf', - old_name='Copie_de', label='Copie de'), - Column('collector', - String(250), - dc='contributor', - old_name='Enregistré_par', label='Collecteur'), - Column('cultural_area', - String(250), - old_name='Aire culturelle', label='Aire culturelle'), - RemovedColumn(old_name='Année_Enreg', - comment='calculé en temps-réel à partir de la date d\'enregistrement'), - Column('generic_style', - generic_styles, - old_name='FormStyl généri', label='Forme / genre générique'), - Column('collector_selection', - String(250), - old_name='ChoixCollecteur', label='Choix du collecteur', - desc='Permet au collecteur de repérer les items les plus intéressants'), - RemovedColumn(old_name='Repère_bande'), - Column('creator_reference', - String(250), - old_name='NroBandNroPièc', label='Référence du déposant'), -) - - - - - - - - - - - - - - - - - diff --git a/docref/spec/texttable.py b/docref/spec/texttable.py deleted file mode 100644 index 3d07d25..0000000 --- a/docref/spec/texttable.py +++ /dev/null @@ -1,155 +0,0 @@ -#coding: utf-8 -import cStringIO,operator - -def indent(rows, hasHeader=False, headerChar=u'-', delim=u' | ', justify=u'left', - separateRows=False, prefix=u'', postfix=u'', wrapfunc=lambda x:x): - """Indents a table by column. - - rows: A sequence of sequences of items, one sequence per row. - - hasHeader: True if the first row consists of the columns' names. - - headerChar: Character to be used for the row separator line - (if hasHeader==True or separateRows==True). - - delim: The column delimiter. - - justify: Determines how are data justified in their column. - Valid values are 'left','right' and 'center'. - - separateRows: True if rows are to be separated by a line - of 'headerChar's. - - prefix: A string prepended to each printed row. - - postfix: A string appended to each printed row. - - wrapfunc: A function f(text) for wrapping text; each element in - the table is first wrapped by this function.""" - # closure for breaking logical rows to physical, using wrapfunc - def rowWrapper(row): - newRows = [wrapfunc(item).split('\n') for item in row] - return [[substr or '' for substr in item] for item in map(None,*newRows)] - # break each logical row into one or more physical ones - logicalRows = [rowWrapper(row) for row in rows] - # columns of physical rows - columns = map(None,*reduce(operator.add,logicalRows)) - # get the maximum of each column by the string length of its items - maxWidths = [max([len(item) for item in column]) for column in columns] - rowSeparator = u"+" + u"+".join([u'-' * (width + len(delim) - 1) for width in maxWidths]) + u"+" - headerSep = u"+" + u"+".join([u'=' * (width + len(delim) - 1) for width in maxWidths]) + u"+" - #headerChar * (len(prefix) + len(postfix) + sum(maxWidths) + \ - # len(delim)*(len(maxWidths)-1)) - #headerSep = u"=" * (len(prefix) + len(postfix) + sum(maxWidths) + \ - # len(delim)*(len(maxWidths)-1)) - # select the appropriate justify method - #justify = {'center':str.center, 'right':str.rjust, 'left':str.ljust}[justify.lower()] - output=u'' - if separateRows: - output += rowSeparator + "\n" - - for physicalRows in logicalRows: - for row in physicalRows: - output += \ - prefix \ - + delim.join([item.ljust(width) for (item,width) in zip(row,maxWidths)]) \ - + postfix + "\n" - if hasHeader: output += headerSep + "\n"; hasHeader=False - elif separateRows: output += rowSeparator + "\n" - return output - -# written by Mike Brown -# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/148061 -def wrap_onspace(text, width): - """ - A word-wrap function that preserves existing line breaks - and most spaces in the text. Expects that existing line - breaks are posix newlines (\n). - """ - return reduce(lambda line, word, width=width: '%s%s%s' % - (line, - ' \n'[(len(line[line.rfind('\n')+1:]) - + len(word.split('\n',1)[0] - ) >= width)], - word), - text.split(' ') - ) - -import re -def wrap_onspace_strict(text, width): - """Similar to wrap_onspace, but enforces the width constraint: - words longer than width are split.""" - wordRegex = re.compile(r'\S{'+str(width)+r',}') - return wrap_onspace(wordRegex.sub(lambda m: wrap_always(m.group(),width),text),width) - -import math -def wrap_always(text, width): - """A simple word-wrap function that wraps text on exactly width characters. - It doesn't split the text in words.""" - return '\n'.join([ text[width*i:width*(i+1)] \ - for i in xrange(int(math.ceil(1.*len(text)/width))) ]) - -if __name__ == '__main__': - labels = ('First Name', 'Last Name', 'Age', 'Position') - data = \ - '''John,Smith,24,Software Engineer - Mary,Brohowski,23,Sales Manager - Aristidis,Papageorgopoulos,28,Senior Reseacher''' - rows = [row.strip().split(',') for row in data.splitlines()] - - print 'Without wrapping function\n' - print indent([labels]+rows, hasHeader=True) - # test indent with different wrapping functions - width = 10 - for wrapper in (wrap_always,wrap_onspace,wrap_onspace_strict): - print 'Wrapping function: %s(x,width=%d)\n' % (wrapper.__name__,width) - print indent([labels]+rows, hasHeader=True, separateRows=True, - prefix='| ', postfix=' |', - wrapfunc=lambda x: wrapper(x,width)) - - # output: - # - #Without wrapping function - # - #First Name | Last Name | Age | Position - #------------------------------------------------------- - #John | Smith | 24 | Software Engineer - #Mary | Brohowski | 23 | Sales Manager - #Aristidis | Papageorgopoulos | 28 | Senior Reseacher - # - #Wrapping function: wrap_always(x,width=10) - # - #---------------------------------------------- - #| First Name | Last Name | Age | Position | - #---------------------------------------------- - #| John | Smith | 24 | Software E | - #| | | | ngineer | - #---------------------------------------------- - #| Mary | Brohowski | 23 | Sales Mana | - #| | | | ger | - #---------------------------------------------- - #| Aristidis | Papageorgo | 28 | Senior Res | - #| | poulos | | eacher | - #---------------------------------------------- - # - #Wrapping function: wrap_onspace(x,width=10) - # - #--------------------------------------------------- - #| First Name | Last Name | Age | Position | - #--------------------------------------------------- - #| John | Smith | 24 | Software | - #| | | | Engineer | - #--------------------------------------------------- - #| Mary | Brohowski | 23 | Sales | - #| | | | Manager | - #--------------------------------------------------- - #| Aristidis | Papageorgopoulos | 28 | Senior | - #| | | | Reseacher | - #--------------------------------------------------- - # - #Wrapping function: wrap_onspace_strict(x,width=10) - # - #--------------------------------------------- - #| First Name | Last Name | Age | Position | - #--------------------------------------------- - #| John | Smith | 24 | Software | - #| | | | Engineer | - #--------------------------------------------- - #| Mary | Brohowski | 23 | Sales | - #| | | | Manager | - #--------------------------------------------- - #| Aristidis | Papageorgo | 28 | Senior | - #| | poulos | | Reseacher | - #--------------------------------------------- - diff --git a/docref/tools/analyse_collection_ids.py b/docref/tools/analyse_collection_ids.py deleted file mode 100644 index d180f55..0000000 --- a/docref/tools/analyse_collection_ids.py +++ /dev/null @@ -1,150 +0,0 @@ -import MySQLdb -import _mysql_exceptions -import re -from sys import stdout - -""" -CREATE TABLE `coll` ( - `cote` varchar(255) default NULL, - `format` varchar(255) default NULL, - `regex` varchar(255) default NULL, - `new_id` varchar(64) default NULL, - `dup` BOOLEAN NOT NULL, - UNIQUE KEY `new_id` (`new_id`), - UNIQUE KEY `cote` (`cote`) -) -""" - - -collection_patterns = [ - { 'format': 'BM.aaa.nnn.mmm', 'regex': r'^(BM)\.([0-9]{3})\.([0-9]{3})\.([0-9]{3})$'}, - { 'format': 'BM.aaaa.nnn.mmm/pp', 'regex': r'^(BM)\.([0-9]{4})\.([0-9]{3})\.([0-9]{3})/[0-9]{2}$'}, - { 'format': 'BM.aaaa.nnn.mmm', 'regex': r'^(BM)\.([0-9]{4})\.([0-9]{3})\.([0-9]{3})$'}, - { 'format': 'BM.aaaa.nnn.mmm/', 'regex': r'^(BM)\.([0-9]{4})\.([0-9]{3})\.([0-9]{3})/$'}, - { 'format': 'BM.aaaa.nnn.mmm/ppp', 'regex': r'^(BM)\.([0-9]{4})\.([0-9]{3})\.([0-9]{3})/[0-9]{3}$'}, - { 'format': 'BM.aaaa.nnn.mm/pp', 'regex': r'^(BM)\.([0-9]{4})\.([0-9]{3})\.([0-9]{2})/[0-9]{2}$'}, - { 'format': 'BM.aaaa.nnn', 'regex': r'^(BM)\.([0-9]{4})\.([0-9]{3})$'}, - { 'format': 'BM.aaa.nnn.mmm/pp', 'regex': r'^(BM)\.([0-9]{3})\.([0-9]{3})\.([0-9]{3})/[0-9]{2}$'}, - { 'format': 'BM.aaa.nnn FANTOME', 'regex': r'^(BM)\.([0-9]{3})\.([0-9]{3}) FANTOME$'}, - { 'format': 'BM.aaa.nnn', 'regex': r'^(BM)\.([0-9]{3})\.([0-9]{3})$'}, - { 'format': 'BM.aaa.nnnBISoo/pp', 'regex': r'^(BM)\.([0-9]{3})\.([0-9]{3})BIS([0-9]{2})/[0-9]{2}$'}, - { 'format': 'BM.aaa.nnn.mmm.ppp', 'regex': r'^(BM)\.([0-9]{3})\.([0-9]{3})\.([0-9]{3})\.[0-9]{3}$'}, - { 'format': 'BM.aaa.nnn.mmm/ppp', 'regex': r'^(BM)\.([0-9]{3})\.([0-9]{3})\.([0-9]{3})/[0-9]{3}$'}, - { 'format': 'BM.aaa.nnn/pp', 'regex': r'^(BM)\.([0-9]{3})\.([0-9]{3})/[0-9]{2}$'}, - { 'format': 'BM.aaa.nnn-BIS.ooo/pp', 'regex': r'^(BM)\.([0-9]{3})\.([0-9]{3})-BIS\.([0-9]{3})/[0-9]{2}$'}, - { 'format': 'BM.aaaa.nnn.mmm/NN', 'regex': r'^(BM)\.([0-9]{4})\.([0-9]{3})\.([0-9]{3})/NN$'}, - { 'format': 'BM.aaa.nnn.mmm/pp-DEPOT', 'regex': r'^(BM)\.([0-9]{3})\.([0-9]{3})\.([0-9]{3})/[0-9]{2}-DEPOT$'}, - { 'format': 'BM.aaa.nnn.mmm-o>p', 'regex': r'^(BM)\.([0-9]{3})\.([0-9]{3})\.([0-9]{3})-[0-9]>[0-9]$'}, - { 'format': 'CY.aaaa.nnn', 'regex': r'^(CY)\.([0-9]{4})\.([0-9]{3})$'}, - { 'format': 'DI.aaaa.nnn.mmm', 'regex': r'^(DI)\.([0-9]{4})\.([0-9]{3})\.([0-9]{3})$'}, - { 'format': 'DI.aaaa.nnn.mmm/pp', 'regex': r'^(DI)\.([0-9]{4})\.([0-9]{3})\.([0-9]{3})/[0-9]{2}$'}, - { 'format': 'DI.aaa.nnn.mmm', 'regex': r'^(DI)\.([0-9]{3})\.([0-9]{3})\.([0-9]{3})$'}, - { 'format': 'DI.aaa.nnn.mmm/pp', 'regex': r'^(DI)\.([0-9]{3})\.([0-9]{3})\.([0-9]{3})/[0-9]{2}$'}, - { 'format': 'DI.aaa.nnn.mmm-o/p', 'regex': r'^(DI)\.([0-9]{3})\.([0-9]{3})\.([0-9]{3})-[0-9]/[0-9]$'}, - { 'format': 'FANTOME 2*', 'regex': r'FANTOME 2\*$'}, -] - -db = MySQLdb.connect(user='root', db='test'); - -rcursor = db.cursor() -wcursor = db.cursor() - -wcursor.execute("UPDATE coll SET format='', new_id = NULL, dup = 0") - -nrow = 0 -for pattern in collection_patterns: - stdout.write('* format: ' + pattern['format'] + '\n') - wcursor.execute("UPDATE coll SET format=%s WHERE cote REGEXP %s", - (pattern['format'], pattern['regex'])) - rcursor.execute("SELECT COUNT(*) FROM coll") - row = rcursor.fetchone() - count = row[0] - rcursor.execute("SELECT cote FROM coll WHERE cote REGEXP %s", (pattern['regex'],)) - row = rcursor.fetchone() - while row: - if nrow % 200 == 0: - stdout.write(" row " + str(nrow) + "/" + str(count) + '\n') - id = row[0] - match = re.match(pattern['regex'], id) - - published = False - year = -1 - serial = -1 - physical = -1 - - if (match.lastindex >= 1): - published = (match.group(1) == 'DI') - if (match.lastindex >= 2): - year = int(match.group(2)) - if (match.lastindex >= 3): - serial = int(match.group(3)) - if (match.lastindex >= 4): - physical = int(match.group(4)) - - if (year == -1 or serial == -1): - stdout.write(' missing year or serial: ' + id + '\n') - else: - tokens = [] - if published: - tokens.append('CNRSMH_E') - else: - tokens.append('CNRSMH_I') - - if year < 1000: - if year < 100: - year += 2000 - else: - year += 1000 - tokens.append(str(year)) - - tokens.append(str(serial).rjust(3, '0')) - - if published: - if physical != -1: - tokens.append(str(physical).rjust(3, '0')) - else: - tokens.append('001') - - new_id = '_'.join(tokens) - - try: - wcursor.execute("UPDATE coll SET new_id = %s WHERE cote = %s", (new_id, id)) - except _mysql_exceptions.IntegrityError, (errno, errstr): - if errno == 1062: - stdout.write(' duplicate entry: ' + id + ' -> ' + new_id + '\n') - wcursor.execute("UPDATE coll SET dup = 1 WHERE cote = %s", (id,)) - else: - raise - - row = rcursor.fetchone() - nrow += 1 - -rcursor.execute("SELECT format, cote, COUNT(*), SUM(dup) FROM coll GROUP BY format"); - -stdout.write("\nFORMAT STATS:\n") -row = rcursor.fetchone() -stdout.write("format\texample\tcount\tduplicates\n"); -while row: - stdout.write(row[0] + "\t" + row[1] + "\t" + str(row[2]) + "\t" + str(row[3]) + '\n') - row = rcursor.fetchone() - -rcursor.execute("SELECT cote FROM coll WHERE new_id IS NULL AND dup = 1") -stdout.write("\nUNCONVERTED IDs (duplicates):\n") -row = rcursor.fetchone() -while row: - stdout.write(row[0] + '\n') - row = rcursor.fetchone() - -rcursor.execute("SELECT cote FROM coll WHERE new_id IS NULL AND dup = 0") -stdout.write("\nUNCONVERTED IDs (non duplicates):\n") -row = rcursor.fetchone() -while row: - stdout.write(row[0] + '\n') - row = rcursor.fetchone() - - - - - - - diff --git a/import/README b/import/README deleted file mode 100644 index 7b6f193..0000000 --- a/import/README +++ /dev/null @@ -1,13 +0,0 @@ - -========================================== -CREM data import instructions and programs -========================================== - -* ``prototype`` : this directory contains scripts to perform an experimental - import of the CREM database into Telemeta 0.3.x. It is only meant as a - proof of concept. -* ``raw_conversion`` : instructions and scripts to perform a full raw conversion - of the CREM database from 4D to MySQL. The result has the same structure - as the original 4D database, and, as such, can't be used directly in - Telemeta. - diff --git a/import/prototype/README b/import/prototype/README deleted file mode 100644 index 88c4a14..0000000 --- a/import/prototype/README +++ /dev/null @@ -1,37 +0,0 @@ -================================================== -CREM data and how to import it into Telemeta 0.3.x -================================================== - -Warning: the following instructions allow you to import the CREM's data -into telemeta. However, it is currently a rather data destructive process, -only meant for demonstration and testing purpose. Do not use this in a -production environment. - -1. Install Telemeta upon MySQL. Initialize the database using Telemeta's - Django models. Ensure that everything is running fine before going any - further. - -2. Run prepare on the source directory. The source directory must contain - text files as they were exported from the 4D database. These files are - expected to be gzipped. - - Example:: - - $ scripts/prepare src/2007-05-09 - -3. Use the import.sql script to insert the data into your MySQL database. - - Example:: - - $ mysql your_telemeta_database < scripts/import.sql - -4. Copy the WAV test file of your choice, into /items/test.wav - This single file is associated with all media items, for testing purpose. - -That should be it. If you want to run Telemeta against SQLite instead of -MySQL, first follow the above instructions to import the data into MySQL. -Then convert your data from MySQL to SQLite, this is a common task, google -about it. - - - diff --git a/import/prototype/scripts/import.sql b/import/prototype/scripts/import.sql deleted file mode 100644 index 0bb05be..0000000 --- a/import/prototype/scripts/import.sql +++ /dev/null @@ -1,31 +0,0 @@ -DELETE FROM telemeta_collection; -LOAD DATA INFILE '/tmp/crem_import/support.txt' INTO TABLE telemeta_collection -FIELDS TERMINATED BY '\t' -LINES TERMINATED BY '\r\n'; - -UPDATE telemeta_collection SET id=REPLACE(id, '/', '--'); -UPDATE telemeta_collection SET copied_from_id = NULL WHERE copied_from_id = ''; - -DELETE FROM telemeta_item; -LOAD DATA INFILE '/tmp/crem_import/phono.txt' INTO TABLE telemeta_item -FIELDS TERMINATED BY '\t' -LINES TERMINATED BY '\r\n'; - -UPDATE telemeta_item SET id=REPLACE(id, ":", "__"); -UPDATE telemeta_item SET id=REPLACE(id, '/', '--'); -UPDATE telemeta_item SET id=REPLACE(id, '?', 'i'); -UPDATE telemeta_item SET collection_id=REPLACE(collection_id, '/', '--'); -UPDATE telemeta_item SET title='' WHERE title='N'; -UPDATE telemeta_item SET etat=REPLACE(etat, ')', '_'); -UPDATE telemeta_item SET etat=REPLACE(etat, '(', '_'); -UPDATE telemeta_item SET file="items/test.wav"; - -DELETE FROM telemeta_physicalformat; -INSERT INTO telemeta_physicalformat (value) - SELECT DISTINCT physical_format FROM telemeta_collection - WHERE physical_format <> '' AND physical_format IS NOT NULL; - -DELETE FROM telemeta_publishingstatus; -INSERT INTO telemeta_publishingstatus (value) - SELECT DISTINCT publishing_status FROM telemeta_collection - WHERE publishing_status <> '' AND publishing_status IS NOT NULL; diff --git a/import/prototype/scripts/prepare b/import/prototype/scripts/prepare deleted file mode 100755 index 92a7618..0000000 --- a/import/prototype/scripts/prepare +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/bash - -if [ "$1" == "" ] -then - echo "Please provide the source directory" - exit 1 -fi - -src=$1 -tmpdir=crem_import -required="support.txt.gz phono.txt.gz" - -for f in $required -do - if ! [ -f $src/$f ] - then - echo "Can't find $f in $src" - exit 1 - fi -done - -if [ -d /tmp/$tmpdir ] -then - rm /tmp/$tmpdir/* -else - mkdir /tmp/$tmpdir -fi - -echo -n "Converting charset and cleaning text files.. " - -zcat $src/support.txt.gz | tail -n +2 \ - | sed 's/^ *//' | sed 's/ *\t */\t/g'| sed 's/ *$//' \ - | iconv -f WINDOWS-1252 -c -t latin1 \ - > /tmp/$tmpdir/support.txt - -zcat $src/phono.txt.gz | tail -n +2 \ - | sed 's/^ *//' | sed 's/ *\t */\t/g'| sed 's/ *$//' \ - | iconv -f WINDOWS-1252 -c -t latin1 | sed '/^\t/d' \ - > /tmp/$tmpdir/phono.txt - -echo "Done" - - diff --git a/import/prototype/src/2007-05-09/phono.txt.gz b/import/prototype/src/2007-05-09/phono.txt.gz deleted file mode 100755 index fd0be4a..0000000 Binary files a/import/prototype/src/2007-05-09/phono.txt.gz and /dev/null differ diff --git a/import/prototype/src/2007-05-09/support.txt.gz b/import/prototype/src/2007-05-09/support.txt.gz deleted file mode 100755 index a7ec8c6..0000000 Binary files a/import/prototype/src/2007-05-09/support.txt.gz and /dev/null differ diff --git a/import/raw_conversion/README b/import/raw_conversion/README deleted file mode 100644 index 17f2195..0000000 --- a/import/raw_conversion/README +++ /dev/null @@ -1,43 +0,0 @@ -========================================================== -Base de données du CREM : conversion brut de 4D vers MySQL -========================================================== - -Le présent document décrit la procédure de conversion brut de la base de -données du CREM de 4D vers MySQL. La base MySQL obtenue a la même structure -que la base originale 4D. - -Cette procédure doit être effectuée par un informaticien. - -Les instructions ci-dessous nécessitent l'emploi de la version 6.5.x de 4D pour -Windows. - -Avertissement: il est fortement recommandé de réaliser ces opérations sur une -copie de la base 4D, et non sur la version de production. - -1. Sur un poste Windows où se trouve la base du CREM, et équipé de 4D 6.5.x, - créer le répertoire C:\export_crem - -2. Lancer 4D, ouvrir la base du CREM, créer une nouvelle méthode 4D avec - le code source fourni dans le fichier ``export.4d.txt``, et lancer cette - méthode de façon à exporter toute la base et les relations dans le - répertoire C:\export_crem - - Cette opération peut prendre plusieurs minutes. Une fenêtre "Export terminé" - s'affiche à la fin. - - Remarque: si vous utilisez une version de démonstration de 4D, vous ne pouvez - pas créer de nouvelle méthode, mais vous pouvez remplacer une méthode existante. - -3. Placer le répertoire export_crem sur un poste linux, de façon à ce qu'il soit - accessible à l'import MySQL, par exemple dans /tmp/export_crem avec 777 pour - permissions - -4. Créer une base MySQL, par exemple: crem - -5. Importer la toutes les données dans la base MySQL avec la commande:: - - ./import /tmp/export_crem | mysql -vvv crem - - Vérifiez que chaque requête se termine par "Query OK" avec "Warnings: 0", - pour vous assurer du bon déroulement de l'opération. - diff --git a/import/raw_conversion/export.4d.txt b/import/raw_conversion/export.4d.txt deleted file mode 100755 index bd30cd6..0000000 --- a/import/raw_conversion/export.4d.txt +++ /dev/null @@ -1,187 +0,0 @@ -`Export de toutes les tables - -C_ALPHA(1;$fieldDelimiter;$recordDelimiter) -C_ALPHA(32;$tableName;$fieldName) -C_ENTIER LONG($numberOfTables;$tableNumber;$numberOfFields;$fieldNumber) -C_ENTIER LONG($numberOfRecords;$fieldType) -C_POINTEUR($tablePtr;$fieldPtr) -C_TEXTE($fieldValue) -C_HEURE($documentReference) -C_REEL($Plateforme) -PROPRIETES PLATE FORME($Plateforme) - -$fieldDelimiter:=Caractere(9)   -$recordDelimiter:=Caractere(10)   - -$numberOfTables:=Nombre de tables   - -Boucle ($tableNumber;1;$numberOfTables)   - - $tablePtr:=Table($tableNumber)   - $tableName:=Nom de la table($tableNumber)   - - $documentReference:=Creer document("C:\export_crem\"+$tableName+".txt";"TEXT")   - - Si (OK=1)   - $numberOfFields:=Nombre de champs($tableNumber)   - - Boucle ($fieldNumber;1;$numberOfFields)   - $fieldName:=Nom du champ($tableNumber;$fieldNumber)   - Si ($fieldNumber#$numberOfFields)   - Si ($Plateforme=Windows ) - ENVOYER PAQUET($documentReference;Mac vers Windows($fieldName)+$fieldDelimiter) -    - Sinon - ENVOYER PAQUET($documentReference;$fieldName+$fieldDelimiter) -    - Fin de si - Sinon - Si ($plateforme=Windows ) - ENVOYER PAQUET($documentReference;Mac vers Windows($fieldName)+$recordDelimiter) -    - Sinon - ENVOYER PAQUET($documentReference;$fieldName+$recordDelimiter) -    - Fin de si - Fin de si - Fin de boucle - - TOUT SELECTIONNER($tablePtr->)   - $numberOfRecords:=Enregistrements trouves($tablePtr->)   - - Boucle ($recordNumber;1;$numberOfRecords)   - - Boucle ($fieldNumber;1;$numberOfFields)   - - $fieldPtr:=Champ($tableNumber;$fieldNumber)   - PROPRIETES CHAMP($fieldPtr;$fieldType)   - -    - - Au cas ou - : (($fieldType=Est un numérique ) | ($fieldType=Est un entier ) | ($fieldType=Est un entier long )) - $fieldValue:=Chaine($fieldPtr->)   - : ($fieldType=Est une date ) - $fieldValue:=Chaine($fieldPtr->;7)   - : ($fieldType=Est une heure ) - $fieldValue:=Chaine($fieldPtr->;1)   - : ($fieldType=Est un booléen ) - -    - - $fieldValue:=Chaine(Num($fieldPtr->);"VRAI;;FAUX")   - : ($fieldType=Est une image ) - $fieldValue:="Image non exportée" - : ($fieldType=Est un BLOB ) - $fieldValue:="BLOB non exporté" - : ($fieldType=Est une sous table ) - $fieldValue:="Sous-table non exportée" - Sinon    - $fieldValue:=$fieldPtr->   - $fieldValue:=Remplacer chaine ($fieldValue; $fieldDelimiter; " ") - $fieldValue:=Remplacer chaine ($fieldValue; $recordDelimiter; " ") - $fieldValue:=Remplacer chaine ($fieldValue; Caractere(13); " ") - Fin de cas - - Si ($fieldNumber#$numberOfFields)   - Si ($Plateforme=Windows ) - ENVOYER PAQUET($documentReference;Mac vers Windows($fieldValue)+$fieldDelimiter)   - Sinon - ENVOYER PAQUET($documentReference;$fieldValue+$fieldDelimiter)   - Fin de si - Sinon - Si ($Plateforme=Windows ) - ENVOYER PAQUET($documentReference;Mac vers Windows($fieldValue)+$recordDelimiter)   -    - Sinon - ENVOYER PAQUET($documentReference;$fieldValue+$recordDelimiter)   -    - Fin de si - - Fin de si - - Fin de boucle - - ENREGISTREMENT SUIVANT($tablePtr->)   - Fin de boucle - - FERMER DOCUMENT($documentReference)   - CHANGER CREATEUR DOCUMENT(Document;"TEXT") - - Fin de si - -Fin de boucle - -`Export des relations des formations - -$tab:=Caractere(9) -$fin:=Caractere(10) -$ret:=Caractere(13) - -$doc:=Creer document("c:\export_crem\Formation.txt";"TXT") -Si (ok=1) - $texte:="Cote_Phono"+$tab+"Instr_Scientif"+$tab+"Instr_Vernacul"+$tab+"Interprète"+$tab+"Total_Instrum"+$fin - ENVOYER PAQUET($doc;Mac vers Windows($texte)) - TOUT SELECTIONNER([Phono]) - Boucle ($i;1;Enregistrements trouves([Phono])) - $cote:=[Phono]Cote_Phono - $cote:=Remplacer chaine($cote; $tab; " ") - $cote:=Remplacer chaine($cote; $fin; " ") - $cote:=Remplacer chaine($cote; $ret; " ") - TOUS LES SOUS ENREGISTREMENTS([Phono]Formation) - Boucle ($j;1;Sous enregistrements trouves([Phono]Formation) - $instr_scientif:=Remplacer chaine([Phono]Formation'Instr_Scientif; $tab; " ") - $instr_scientif:=Remplacer chaine($instr_scientif; $fin; " ") - $instr_scientif:=Remplacer chaine($instr_scientif; $ret; " ") - $instr_vernacul:=Remplacer chaine([Phono]Formation'Instr_Vernacul; $tab; " ") - $instr_vernacul:=Remplacer chaine($instr_vernacul; $fin; " ") - $instr_vernacul:=Remplacer chaine($instr_vernacul; $ret; " ") - $interprete:=Remplacer chaine([Phono]Formation'Interprète; $tab; " ") - $interprete:=Remplacer chaine($interprete; $fin; " ") - $interprete:=Remplacer chaine($interprete; $ret; " ") - $total:=Remplacer chaine([Phono]Formation'Total_Instrum; $tab; " ") - $total:=Remplacer chaine($total; $fin; " ") - $total:=Remplacer chaine($total; $ret; " ") - $texte:=$cote+$tab+$instr_scientif+$tab+$instr_vernacul+$tab+$interprete+$tab+$total+$fin - ENVOYER PAQUET($doc;Mac vers Windows($texte)) - SOUS ENREGISTREMENT SUIVANT([Phono]Formation) - Fin de boucle - LIBERER ENREGISTREMENT([Phono]) - ENREGISTREMENT SUIVANT([Phono]) - Fin de boucle - - FERMER DOCUMENT($doc) - -Fin de si - -`Export des relations des mots clés - -$doc:=Creer document("c:\export_crem\Fonction_Usage.txt";"TXT") -Si (ok=1) - $texte:="Cote_Phono"+$tab+"Mot_Clef"+$fin - ENVOYER PAQUET($doc;Mac vers Windows($texte)) - TOUT SELECTIONNER([Phono]) - Boucle ($i;1;Enregistrements trouves([Phono])) - $cote:=[Phono]Cote_Phono - $cote:=Remplacer chaine($cote; $tab; " ") - $cote:=Remplacer chaine($cote; $fin; " ") - $cote:=Remplacer chaine($cote; $ret; " ") - TOUS LES SOUS ENREGISTREMENTS([Phono]Fonction_Usage) - Boucle ($j;1;Sous enregistrements trouves([Phono]Fonction_Usage) - $mot_clef:=Remplacer chaine([Phono]Fonction_Usage'Mot_Clef; $tab; " ") - $mot_clef:=Remplacer chaine($mot_clef; $fin; " ") - $mot_clef:=Remplacer chaine($mot_clef; $ret; " ") - $texte:=$cote+$tab+$mot_clef+$fin - ENVOYER PAQUET($doc;Mac vers Windows($texte)) - SOUS ENREGISTREMENT SUIVANT([Phono]Fonction_Usage) - Fin de boucle - LIBERER ENREGISTREMENT([Phono]) - ENREGISTREMENT SUIVANT([Phono]) - Fin de boucle - - FERMER DOCUMENT($doc) - -Fin de si - - -ALERTE("Export terminé.") diff --git a/import/raw_conversion/import b/import/raw_conversion/import deleted file mode 100755 index a020f39..0000000 --- a/import/raw_conversion/import +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/bash - -function extract_enum -{ - to_table=$1 - from_table=$2 - from_field=$3 - echo "DROP TABLE IF EXISTS \`$to_table\`;" - echo "CREATE TABLE \`$to_table\` (value TEXT NOT NULL) CHARSET=latin1;" - echo "INSERT INTO \`$to_table\` SELECT DISTINCT \`$from_field\` FROM \`$from_table\` WHERE \`$from_field\` <> '';"; -} - -src=$1 -cd $src - -echo "SET NAMES 'latin1';" -echo - -chmod o+r *.txt - -ls *.txt | while read filename -do - table=$(echo $filename | sed 's/.txt//') - echo "DROP TABLE IF EXISTS \`$table\`;" - echo "CREATE TABLE \`$table\` (" - head -n1 $filename | tr '\t' '\n' | head -n-1 | sed 's/^/ `/' | sed 's/$/` TEXT NOT NULL,/' - head -n1 $filename | tr '\t' '\n' | tail -n1 | sed 's/^/ `/' | sed 's/$/` TEXT NOT NULL/' - echo ") CHARSET=latin1;" - echo - echo "LOAD DATA INFILE '$src/$filename'" - echo " INTO TABLE \`$table\`" - echo " CHARACTER SET 'latin1'" - echo " FIELDS TERMINATED BY '\t' ESCAPED BY '' LINES TERMINATED BY '\n'" - echo " IGNORE 1 LINES;" - echo "SHOW WARNINGS;" - echo -done - -extract_enum Format Support Format -extract_enum Réédition Support Réédition -extract_enum Mode_Acqui Support Mode_Acqui -extract_enum Rédacteur_Fiche Support Rédacteur_Fiche -extract_enum Saisie_Fiche Support Saisie_Fiche -extract_enum Droit_Utiliser Support Droit_Utiliser -extract_enum Terrain_ou_Autr Support Terrain_ou_Autr -extract_enum Numérisation Support Numérisation -extract_enum "FormStyl généri" Phono "FormStyl généri" -extract_enum Editeur1 Support Editeur -extract_enum Collection_Serie Support Collect_Série - diff --git a/trunk/docref/crem.sql b/trunk/docref/crem.sql new file mode 100644 index 0000000..4f60c51 --- /dev/null +++ b/trunk/docref/crem.sql @@ -0,0 +1,378 @@ +-- +-- Copyright Samalyse SARL, 2008 +-- Auteur: Olivier Guilyardi +-- +-- Structure de la nouvelle base du CREM +-- +-- Ce logiciel est régi par la licence CeCILL soumise au droit français et +-- respectant les principes de diffusion des logiciels libres. Vous pouvez +-- utiliser, modifier et/ou redistribuer ce programme sous les conditions +-- de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA +-- sur le site "http://www.cecill.info". +-- +-- En contrepartie de l'accessibilité au code source et des droits de copie, +-- de modification et de redistribution accordés par cette licence, il n'est +-- offert aux utilisateurs qu'une garantie limitée. Pour les mêmes raisons, +-- seule une responsabilité restreinte pèse sur l'auteur du programme, le +-- titulaire des droits patrimoniaux et les concédants successifs. +-- +-- A cet égard l'attention de l'utilisateur est attirée sur les risques +-- associés au chargement, à l'utilisation, à la modification et/ou au +-- développement et à la reproduction du logiciel par l'utilisateur étant +-- donné sa spécificité de logiciel libre, qui peut le rendre complexe à +-- manipuler et qui le réserve donc à des développeurs et des professionnels +-- avertis possédant des connaissances informatiques approfondies. Les +-- utilisateurs sont donc invités à charger et tester l'adéquation du +-- logiciel à leurs besoins dans des conditions permettant d'assurer la +-- sécurité de leurs systèmes et ou de leurs données et, plus généralement, +-- à l'utiliser et l'exploiter dans les mêmes conditions de sécurité. +-- +-- Le fait que vous puissiez accéder à cet en-tête signifie que vous avez +-- pris connaissance de la licence CeCILL, et que vous en avez accepté les +-- termes. +-- +-- SVN:$Id$ +-- + +-- +-- Enumérations simples +-- + +CREATE TABLE physical_formats ( + id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, + value VARCHAR(250) NOT NULL +); + +CREATE TABLE publishing_status ( + id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, + value VARCHAR(250) NOT NULL +); + +CREATE TABLE acquisition_modes ( + id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, + value VARCHAR(250) NOT NULL +); + +CREATE TABLE metadata_authors ( + id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, + value VARCHAR(250) NOT NULL +); + +CREATE TABLE metadata_writers ( + id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, + value VARCHAR(250) NOT NULL +); + +CREATE TABLE legal_rights ( + id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, + value VARCHAR(250) NOT NULL +); + +CREATE TABLE recording_contexts ( + id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, + value VARCHAR(250) NOT NULL +); + +CREATE TABLE ad_conversions ( + id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, + value VARCHAR(250) NOT NULL +); + +CREATE TABLE vernacular_styles ( + id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, + value VARCHAR(250) NOT NULL +); + +CREATE TABLE generic_styles ( + id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, + value VARCHAR(250) NOT NULL +); + +-- +-- Editeurs et collections +-- + +CREATE TABLE publishers ( + id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, + value VARCHAR(250) NOT NULL +); + +CREATE TABLE publisher_collections ( + id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, + publisher_id INTEGER NOT NULL, + value VARCHAR(250) NOT NULL, + + FOREIGN KEY(publisher_id) REFERENCES publishers (id) +); + +-- +-- Thésaurus géographique +-- + +CREATE TABLE location_types ( + id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, + type VARCHAR(250) NOT NULL +); + +CREATE TABLE locations ( + name VARCHAR(250) NOT NULL PRIMARY KEY, + type ENUM('country', 'continent', 'other'), + complete_type_id INTEGER NOT NULL, + current_name VARCHAR(250), + is_authoritative BOOLEAN NOT NULL, + + FOREIGN KEY(current_name) REFERENCES locations (name), + FOREIGN KEY(complete_type_id) REFERENCES location_types (id) +); + +CREATE TABLE location_aliases ( + location_name VARCHAR(250) NOT NULL, + alias VARCHAR(250) NOT NULL, + is_authoritative BOOLEAN NOT NULL, + + PRIMARY KEY(location_name, alias), + FOREIGN KEY(location_name) REFERENCES locations (name) +); + +CREATE TABLE location_relations ( + location_name VARCHAR(250) NOT NULL, + parent_location_name VARCHAR(250) NOT NULL, + + PRIMARY KEY(location_name, parent_location_name), + FOREIGN KEY(location_name) REFERENCES locations (name), + FOREIGN KEY(parent_location_name) REFERENCES locations (name) +); + +-- +-- Ethnies +-- + +CREATE TABLE ethnic_groups ( + id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, + name VARCHAR(250) NOT NULL +); + +CREATE TABLE ethnic_group_aliases ( + ethnic_group_id INTEGER NOT NULL, + name VARCHAR(250) NOT NULL, + + FOREIGN KEY(ethnic_group_id) REFERENCES ethnic_groups (id) +); + +-- +-- Collections +-- + +CREATE TABLE media_collections ( + id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, + reference VARCHAR(250) NOT NULL UNIQUE, + physical_format_id INTEGER NOT NULL, + old_code VARCHAR(250) NOT NULL UNIQUE, + code VARCHAR(250) NOT NULL UNIQUE, + title VARCHAR(250) NOT NULL, + alt_title VARCHAR(250) NOT NULL, + physical_items_num INTEGER NOT NULL, + publishing_status_id INTEGER NOT NULL, + creator VARCHAR(250) NOT NULL, + booklet_author VARCHAR(250) NOT NULL, + booklet_description TEXT NOT NULL, + collector VARCHAR(250) NOT NULL, + collector_is_creator BOOLEAN NOT NULL, + publisher_id INTEGER NOT NULL, + year_published INTEGER NOT NULL, + publisher_collection_id INTEGER NOT NULL, + publisher_serial VARCHAR(250) NOT NULL, + external_references TEXT NOT NULL, + acquisition_mode_id INTEGER NOT NULL, + comment TEXT NOT NULL, + metadata_author_id INTEGER NOT NULL, + metadata_writer_id INTEGER NOT NULL, + legal_rights_id INTEGER NOT NULL, + alt_ids VARCHAR(250) NOT NULL, + recorded_from_year INTEGER NOT NULL, + recorded_to_year INTEGER NOT NULL, + recording_context_id INTEGER NOT NULL, + approx_duration TIME NOT NULL, + doctype_code INTEGER NOT NULL, + travail VARCHAR(250) NOT NULL, + state VARCHAR(250) NOT NULL, + cnrs_contributor VARCHAR(250) NOT NULL, + items_done VARCHAR(250) NOT NULL, + a_informer_07_03 VARCHAR(250) NOT NULL, + ad_conversion_id INTEGER NOT NULL, + public_access ENUM('none', 'metadata', 'full') NOT NULL, + + FOREIGN KEY(ad_conversion_id) REFERENCES ad_conversions (id), + FOREIGN KEY(publisher_collection_id) REFERENCES publisher_collections (id), + FOREIGN KEY(recording_context_id) REFERENCES recording_contexts (id), + FOREIGN KEY(publisher_id) REFERENCES publishers (id), + FOREIGN KEY(metadata_author_id) REFERENCES metadata_authors (id), + FOREIGN KEY(physical_format_id) REFERENCES physical_formats (id), + FOREIGN KEY(metadata_writer_id) REFERENCES metadata_writers (id), + FOREIGN KEY(legal_rights_id) REFERENCES legal_rights (id), + FOREIGN KEY(acquisition_mode_id) REFERENCES acquisition_modes (id), + FOREIGN KEY(publishing_status_id) REFERENCES publishing_status (id) +); + +-- +-- Items +-- + +CREATE TABLE media_items ( + id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, + collection_id INTEGER NOT NULL, + track VARCHAR(250) NOT NULL, + code VARCHAR(250) NOT NULL, + approx_duration TIME NOT NULL, + recorded_from_date DATE NOT NULL, + recorded_to_date DATE NOT NULL, + location_name VARCHAR(250) NOT NULL, + location_comment VARCHAR(250) NOT NULL, + ethnic_group_id INTEGER NOT NULL, + title VARCHAR(250) NOT NULL, + alt_title VARCHAR(250) NOT NULL, + author VARCHAR(250) NOT NULL, + vernacular_style_id INTEGER NOT NULL, + context_comment TEXT NOT NULL, + external_references VARCHAR(250) NOT NULL, + moda_execut VARCHAR(250) NOT NULL, + copied_from_item_id INTEGER, + collector VARCHAR(250) NOT NULL, + cultural_area VARCHAR(250) NOT NULL, + generic_style_id INTEGER NOT NULL, + collector_selection VARCHAR(250) NOT NULL, + creator_reference VARCHAR(250) NOT NULL, + filename VARCHAR(250) NOT NULL, + public_access ENUM('none', 'metadata', 'full') NOT NULL, + + FOREIGN KEY(ethnic_group_id) REFERENCES ethnic_groups (id), + FOREIGN KEY(collection_id) REFERENCES media_collections (id), + FOREIGN KEY(vernacular_style_id) REFERENCES vernacular_styles (id), + FOREIGN KEY(location_name) REFERENCES locations (name), + FOREIGN KEY(copied_from_item_id) REFERENCES media_items (id), + FOREIGN KEY(generic_style_id) REFERENCES generic_styles (id) +); + +-- +-- Parties d'item/marqueurs +-- + +CREATE TABLE media_parts ( + id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, + item_id INTEGER NOT NULL, + title VARCHAR(250) NOT NULL, + start FLOAT NOT NULL, + end FLOAT NOT NULL, + + FOREIGN KEY(item_id) REFERENCES media_items (id) +); + +-- +-- Instruments et formations +-- + +CREATE TABLE instruments ( + id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, + name VARCHAR(250) NOT NULL +); + +CREATE TABLE instrument_relations ( + instrument_id INTEGER NOT NULL, + parent_instrument_id INTEGER NOT NULL, + + FOREIGN KEY(instrument_id) REFERENCES instruments (id), + FOREIGN KEY(parent_instrument_id) REFERENCES instruments (id) +); + +CREATE TABLE instrument_aliases ( + id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, + name VARCHAR(250) NOT NULL +); + +CREATE TABLE instrument_alias_relations ( + alias_id INTEGER NOT NULL, + instrument_id INTEGER NOT NULL, + + FOREIGN KEY(alias_id) REFERENCES instrument_aliases (id), + FOREIGN KEY(instrument_id) REFERENCES instruments (id) +); + +CREATE TABLE media_item_performances ( + media_item_id INTEGER NOT NULL, + instrument_id INTEGER NOT NULL, + alias_id INTEGER NOT NULL, + instruments_num VARCHAR(250) NOT NULL, + musicians VARCHAR(250) NOT NULL, + + FOREIGN KEY(media_item_id) REFERENCES media_items (id), + FOREIGN KEY(instrument_id) REFERENCES instruments (id), + FOREIGN KEY(alias_id) REFERENCES instrument_aliases (id) +); + +-- +-- Contexte ethnographique +-- + +CREATE TABLE context_keywords ( + id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, + value VARCHAR(250) NOT NULL +); + +CREATE TABLE media_item_keywords ( + item_id INTEGER NOT NULL, + keyword_id INTEGER NOT NULL, + + PRIMARY KEY(item_id, keyword_id), + FOREIGN KEY(item_id) REFERENCES media_items (id), + FOREIGN KEY(keyword_id) REFERENCES context_keywords (id) +); + +-- +-- Utilisateurs +-- + +CREATE TABLE users ( + username VARCHAR(64) NOT NULL PRIMARY KEY, + level ENUM ('user', 'maintainer', 'admin') NOT NULL, + first_name VARCHAR(250) NOT NULL, + last_name VARCHAR(250) NOT NULL, + phone VARCHAR(250) NOT NULL, + email VARCHAR(250) NOT NULL +); + +-- +-- Séléctions +-- + +CREATE TABLE playlists ( + id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, + owner_username VARCHAR(250) NOT NULL, + name VARCHAR(250) NOT NULL, + + FOREIGN KEY(owner_username) REFERENCES users (username) +); + +CREATE TABLE playlist_resources ( + playlist_id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, + resource_type ENUM('item', 'collection') NOT NULL, + resource_id INTEGER NOT NULL, + + FOREIGN KEY(playlist_id) REFERENCES playlists (id) +); + + +-- +-- Historique des modifications +-- + +CREATE TABLE revisions ( + id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, + element_type VARCHAR(32) NOT NULL, + element_id INTEGER NOT NULL, + change_type ENUM('create', 'update', 'delete') NOT NULL, + time DATETIME NOT NULL, + username VARCHAR(64) NOT NULL, + + FOREIGN KEY(username) REFERENCES users (username) +); + diff --git a/trunk/docref/crem.zargo b/trunk/docref/crem.zargo new file mode 100644 index 0000000..4f7b7e8 Binary files /dev/null and b/trunk/docref/crem.zargo differ diff --git a/trunk/docref/docref-0.1-prealpha.odt b/trunk/docref/docref-0.1-prealpha.odt new file mode 100644 index 0000000..4c8a8df Binary files /dev/null and b/trunk/docref/docref-0.1-prealpha.odt differ diff --git a/trunk/docref/docref-0.2-prealpha.odt b/trunk/docref/docref-0.2-prealpha.odt new file mode 100644 index 0000000..79cba1f Binary files /dev/null and b/trunk/docref/docref-0.2-prealpha.odt differ diff --git a/trunk/docref/docref-0.3-alpha.odt b/trunk/docref/docref-0.3-alpha.odt new file mode 100644 index 0000000..4295755 Binary files /dev/null and b/trunk/docref/docref-0.3-alpha.odt differ diff --git a/trunk/docref/docref-0.4-beta.odt b/trunk/docref/docref-0.4-beta.odt new file mode 100644 index 0000000..f043e96 Binary files /dev/null and b/trunk/docref/docref-0.4-beta.odt differ diff --git a/trunk/docref/docref.odt b/trunk/docref/docref.odt new file mode 100644 index 0000000..5e96532 Binary files /dev/null and b/trunk/docref/docref.odt differ diff --git a/trunk/docref/spec/build.sh b/trunk/docref/spec/build.sh new file mode 100644 index 0000000..14af7e3 --- /dev/null +++ b/trunk/docref/spec/build.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +python parse.py +cd build +rst2html docref.txt docref.html && rst2latex docref.txt docref.tex && pdflatex docref.tex + diff --git a/trunk/docref/spec/docref.txt b/trunk/docref/spec/docref.txt new file mode 100644 index 0000000..48bb608 --- /dev/null +++ b/trunk/docref/spec/docref.txt @@ -0,0 +1,223 @@ + + +=================================================================== +Recommandations pour la réorganisation de la base de donnée du CREM +=================================================================== +------------------------------------ +Document de référence, version alpha +------------------------------------ + + +I - Enjeux +========== + +I.1 - Recherche d'informations +------------------------------ + +L'analyse de la structure de données et la rencontre des personnes concernées par son usage +permettent de délimiter des enjeux majeurs. Il apparaît notamment que le fond documentaire +que constitue cette base n'est actuellement pas mis à profit comme il pourrait l'être. Cette +base est largement sous-utilisée, les chercheurs, pour certains, ne l'utilisent pas du tout. + +La raison principale de cette situation est le fait que l'environnement technique et la +structure de la base ont été conçus pour s'inscrire dans un environnement documentaire +traditionnel, qui implique généralement de prendre contact avec un documentaliste pour effectuer +une recherche. Le documentaliste est un spécialiste de la base, il possède les connaissances +techniques nécessaires à sa consultation. + +Mais à l'heure d'Internet, ce processus de recherche est trop lourd et inadapté, en un mot +: obsolète. Les chercheurs lui préfèrent d'autres fonds documentaires accessibles en ligne, +de façon immédiate, et équipés d'outils de recherche puissants et ergonomiques. + +L'enjeu principal de la réorganisation de la base du CREM consiste donc à : sous-tendre le +développement d'un outil moderne de gestion et de consultation en ligne, avec des fonctions +de recherche puissantes et intuitives déterminer et améliorer les données de la base qui +sont prioritaires pour la recherche d'information + +En de-ça des-dits champs prioritaires, il existe un grand nombre d'information techniques de +second ordre, qui soit ne sont utiles qu'aux documentalistes, soit ne présentent pas d'intérêt +majeur pour la recherche d'information. Ces informations peuvent être conservées telles quelles, +sans grand effort de réorganisation, et resteront ainsi disponibles lors de la consultation +individuelle des fiches. + +En procédant de cette façon, c'est à dire en délimitant les-dîtes priorités, il semble +possible de dégager une véritable plus-value, de rendre le fond documentaire du CREM plus vivant, +sans pour autant engager des moyens démesurés dans la réorganisation de la base de donnée. + +I.2 - Gestion et mise à jour des données +---------------------------------------- + +Il est entendu qu'au delà de la consultation d'information, il s'agit également de faciliter +la gestion des données, leur mise à jour. Cette question implique pour une large part des +problématiques d'ordre ergonomique, liées au développement d'un outil logiciel autour de la +base, ce qui n'entre pas dans le cadre de la réorganisation de la base de données. + +Cependant, au niveau de la base, certains choix sont structurant. Par exemple l'emploi d'une +liste hiérarchisée de lieux telle que le Thesaurus of Geographical Names (TGN, recommandé par +Dublin Core), permet, en choisissant une région, une sous-région ou un village, de renseigner +automatiquement le pays (et les autres zones géographiques intermédiaires), ce qui diminue +l'effort et prévient les erreurs de saisie. + +Pour un grand nombre de champs, l'emploi d'énumérations (liste de valeurs valides pour +un champ donné) facilite et valide déjà la mise à jour des données. Cet aspect de la base +devra être conservé. + +Cependant, il semble que l'enjeu majeur de la réorganisation, du point de vue de la gestion +des données, est de permettre un travail collaboratif, entre chercheurs et documentalistes. C'est +là, d'une manière générale, ce qui permet sur Internet de rendre un fond documentaire vivant. + +Dans le cadre du CREM, il serait ainsi idéal d'amener les chercheurs à alimenter la base de +façon autonome, en sus des documentalistes dont c'est le métier. Ce serait là une véritable +nouveauté, représentant un fort potentiel d'enrichissement des données. + +D'une façon générale, une application en ligne ("webifiée") bien conçue se prête +très bien au travail collaboratif. Cependant, il semble que dans notre cas, les potentielles +contributions des chercheurs se heurtent à une question importante de confidentialité et +de propriété intellectuelle. Des cas ont en effet été rapportés d'usage détournés du +fruit du travail du centre de recherche, et d'une manière générale, il semble qu'il faille +observer une grande prudence pour la mise en commun d'enregistrement sonores et autres données, +qui représentent une matière précieuse aux yeux des chercheurs. + +La sécurité informatique est pour une large part distinct de la base de donnée ; elle +implique des efforts particuliers au niveau du développement applicatif, et de l'administration +de l'infrastructure réseau. + +Cependant, au niveau de la base de donnée, il est possible de mettre l'accent sur la +propriété des données. Chaque ressource (collection, item) peut en effet se voir attribuer +un propriétaire. Le dit propriétaire devrait ensuite pouvoir choisir quel autre utilisateur +et/ou groupe d'utilisateur est autorisé à consulter, écouter, et/ou modifier la ressource. + +En rassurant ainsi les chercheurs, il est envisageable que la base s'enrichisse notablement +par leurs contributions, dont certaines d'abord privées, pourront, à leur guise, devenir +petit à petit accessibles à un nombre grandissant d'utilisateurs et de groupes de travail. + +I.3 - Données prioritaires + +Après consultation des différents utilisateurs il apparaît que les meta-données principales +pour chaque item sont : + +* l'identifiant unique de l'item +* le titre de l'item +* la zone géographique +* le nom du collecteur, c'est à dire le chercheur qui a collecté cet enregistrement +* les instruments de musique utilisés +* l'année d'enregistrement +* le contexte ethnographique +* l'ethnie + +Il s'agit d'apporter une attention particulière à celles-ci, notamment en les normalisant, +pour faciliter la recherche d'informations, mais aussi pour l'ajout et la gestion simplifiés +d'items. + +Les autres données pourront être conservées telles quelles sans grand effort de normalisation. + +I.4 - Dublin Core +----------------- + +... + +II - Modalités de conversion/réorganisation de la base +====================================================== + +II.1 - Enumérations simples +--------------------------- + +dynamic:tables.describe_enums() + +II.2 - Collections +------------------ + +Ancien nom de table : support + +Nouveau nom de table : media_collections + +II.2.1 - Champs convertis +~~~~~~~~~~~~~~~~~~~~~~~~~ + +dynamic:tables.media_collections.describe_conversion() + +II.2.2 - Nouveaux champs +~~~~~~~~~~~~~~~~~~~~~~~~ + +dynamic:tables.media_collections.describe_new_fields() + +II.2.3 - Champs supprimés +~~~~~~~~~~~~~~~~~~~~~~~~~ + +dynamic:tables.media_collections.describe_removed_fields() + +II.3 - Items +------------ + +Ancien nom de table : phono + +Nouveau nom de table : media_items + +II.3.1 - Champs convertis +~~~~~~~~~~~~~~~~~~~~~~~~~ + +dynamic:tables.media_items.describe_conversion() + +II.3.2 - Nouveaux champs +~~~~~~~~~~~~~~~~~~~~~~~~ + +dynamic:tables.media_items.describe_new_fields() + +II.3.3 - Champs supprimés +~~~~~~~~~~~~~~~~~~~~~~~~~ + +dynamic:tables.media_items.describe_removed_fields() + +II.4 - Sélections +----------------- + +II.4.1 - Liste +~~~~~~~~~~~~~~ + +Nom de table: +dynamic:tables.media_playlists.name + +dynamic:tables.media_playlists.describe_new_fields() + +II.4.2 - Table de relation interne +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Nom de table: +dynamic:tables.media_playlist_resources.name + +dynamic:tables.media_playlist_resources.describe_new_fields() + +II.5 - Thesaurus Géographique +----------------------------- + +II.5.1 - Lieux +~~~~~~~~~~~~~~ + +Nom de table: +dynamic:tables.locations.name + +dynamic:tables.locations.describe_new_fields() + +II.5.2 - Alias des lieux +~~~~~~~~~~~~~~~~~~~~~~~~ + +Nom de table: +dynamic:tables.location_aliases.name + +dynamic:tables.location_aliases.describe_new_fields() + +II.5.3 - Relations hiérarchiques +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Nom de table: +dynamic:tables.location_relations.name + +dynamic:tables.location_relations.describe_new_fields() + +II.6 - Utilisateurs +------------------- + +Nom de table: +dynamic:tables.users.name + +dynamic:tables.users.describe_new_fields() diff --git a/trunk/docref/spec/elements.py b/trunk/docref/spec/elements.py new file mode 100644 index 0000000..e46b8d7 --- /dev/null +++ b/trunk/docref/spec/elements.py @@ -0,0 +1,136 @@ +#coding: utf-8 +import sqlalchemy +import texttable + +def make_table(rows, width=20): + return texttable.indent(rows, hasHeader = True, separateRows = True, + prefix=u'| ', postfix=u' |', + wrapfunc = lambda x: texttable.wrap_onspace(x, width=width)) + +def describe_enums(metadata): + rows = [['Nom interne', 'Ancien nom', 'Description']] + for enum in metadata.enums: + rows.append([enum.name, enum.old_name, enum.label]) + return make_table(rows, 40) + +class Column(sqlalchemy.Column): + old_name = '' + label = '' + desc = '' + dc = '' + comment = '' + conversion = '' + enum = None + + def __init__(self, name, type, *args, **kwargs): + parent_args = {} + for key, value in kwargs.items(): + if key == 'old_name': + if isinstance(value, list): + self.old_name = unicode(",\n".join(value), 'utf-8') + #self.old_name = [] + #for item in value: + # self.old_name.append(unicode(item, 'utf-8')) + else: + self.old_name = unicode(value, 'utf-8') + elif key == 'label': + self.label = unicode(value, 'utf-8') + elif key == 'desc': + self.desc = unicode(value, 'utf-8') + elif key == 'dc': + self.dc = value + elif key == 'comment': + self.comment = unicode(value, 'utf-8') + elif key == 'conversion': + self.conversion = unicode(value, 'utf-8') + else: + parent_args[key] = value + + if isinstance(type, Enumeration): + args = (sqlalchemy.ForeignKey(type.name + '.id'),) + args + self.enum = type + type = sqlalchemy.Integer + + super(Column, self).__init__(name, type, *args, **parent_args) + +class RemovedColumn(object): + old_name = '' + comment = '' + + def __init__(self, old_name, comment=''): + self.old_name = unicode(old_name, 'utf-8') + self.comment = unicode(comment, 'utf-8') + +class Table(sqlalchemy.Table): + + def __init__(self, table_name, metadata, label, *args): + self.label = unicode(label, 'utf-8') + real_columns = [] + self.removed_columns = [] + for column in args: + if isinstance(column, RemovedColumn): + self.removed_columns.append(column) + else: + real_columns.append(column) + super(Table, self).__init__(table_name, metadata, *real_columns) + + + def describe_new_fields(self): + rows = [['Nom', 'Nom interne', 'Dublin Core']] + for column in self.columns: + if not column.old_name: + rows.append([column.label, column.name, column.dc]) + + return make_table(rows) + + def describe_conversion(self): + rows = [['Nouveau nom', 'Ancien nom', 'Nouveau nom interne', 'Dublin Core']] + for column in self.columns: + if column.old_name: + rows.append([column.label, column.old_name, column.name, column.dc]) + + return make_table(rows) + + def describe_removed_fields(self): + rows = [['Nom', 'Commentaire']] + for column in self.removed_columns: + rows.append([column.old_name, column.comment]) + + return make_table(rows, 50) + + def to_dot(self): + dot = u'digraph g {\n' + dot += ' charset = "utf-8";\n' + dot += ' node [shape=record, charset="utf-8"];\n' + dot += ' rankdir = LR;\n' + dot += ' subgraph cluster_new_fields {\n' + dot += ' label = "Nouveaux champs";\n' + dot += ' color = black;\n' + old_fields = '' + conversion = '' + for column in self.columns: + dot += ' ' + column.name + '[label = "{' + column.label + ' | ' + column.name + '}"];\n' + if column.old_name: + old_fields += ' old_' + column.name + '[label = "' + column.old_name + '"];\n' + conversion += ' old_' + column.name + ' -> ' + column.name + ';\n' + dot += ' }\n' + dot += ' subgraph cluster_old_fields {\n' + dot += ' label = "Anciens champs";\n' + dot += ' color = black;\n' + dot += old_fields + dot += ' }\n' + dot += conversion + dot += '}\n' + return dot + +class Enumeration(Table): + + def __init__(self, name, metadata, label='', old_name=''): + self.old_name = unicode(old_name, 'utf-8') + if not hasattr(metadata, 'enums'): + metadata.enums = [] + metadata.enums.append(self) + super(Enumeration, self).__init__(name, metadata, label, + Column('id', sqlalchemy.Integer, primary_key=True), + Column('value', sqlalchemy.String(250), unique=True) + ) diff --git a/trunk/docref/spec/parse.py b/trunk/docref/spec/parse.py new file mode 100644 index 0000000..535832c --- /dev/null +++ b/trunk/docref/spec/parse.py @@ -0,0 +1,18 @@ + +import tables +import codecs +input = codecs.open('docref.txt', 'r', "utf-8") +output = codecs.open('build/docref.txt', 'w', "iso-8859-1") + +for line in input: + if line[0:8] == 'dynamic:': + output.write(eval(line[8:], globals(), locals()) + "\n") + else: + output.write(line) + +input.close() +output.close() + +output = codecs.open('build/collections.dot', 'w', 'utf-8') +output.write(tables.media_collections.to_dot()) +output.close() diff --git a/trunk/docref/spec/staticenum.py b/trunk/docref/spec/staticenum.py new file mode 100644 index 0000000..d364f5b --- /dev/null +++ b/trunk/docref/spec/staticenum.py @@ -0,0 +1,69 @@ +#!python + +## The MIT License + +## Copyright (c) + +## Permission is hereby granted, free of charge, to any person obtaining a copy +## of this software and associated documentation files (the "Software"), to deal +## in the Software without restriction, including without limitation the rights +## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +## copies of the Software, and to permit persons to whom the Software is +## furnished to do so, subject to the following conditions: + +## The above copyright notice and this permission notice shall be included in +## all copies or substantial portions of the Software. + +## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +## THE SOFTWARE. + + +from sqlalchemy import types, exceptions + +class StaticEnum(types.TypeDecorator): + impl = types.Unicode + + def __init__(self, values, empty_to_none=False, strict=False): + """Emulate an Enum type. + + values: + A list of valid values for this column + empty_to_none: + Optional, treat the empty string '' as None + strict: + Also insist that columns read from the database are in the + list of valid values. Note that, with strict=True, you won't + be able to clean out bad data from the database through your + code. + """ + + if values is None or len(values) is 0: + raise exceptions.AssertionError('StaticEnum requires a list of values') + self.empty_to_none = empty_to_none + self.strict = strict + self.values = values[:] + + # The length of the string/unicode column should be the longest string + # in values + size = max([len(v) for v in values if v is not None]) + super(StaticEnum, self).__init__(size) + + + def convert_bind_param(self, value, engine): + if self.empty_to_none and value is '': + value = None + if value not in self.values: + raise exceptions.AssertionError('"%s" not in StaticEnum.values' % value) + return super(StaticEnum, self).convert_bind_param(value, engine) + + + def convert_result_value(self, value, engine): + if self.strict and value not in self.values: + raise exceptions.AssertionError('"%s" not in StaticEnum.values' % value) + return super(StaticEnum, self).convert_result_value(value, engine) + diff --git a/trunk/docref/spec/tables.py b/trunk/docref/spec/tables.py new file mode 100644 index 0000000..41fd6d4 --- /dev/null +++ b/trunk/docref/spec/tables.py @@ -0,0 +1,331 @@ +#coding: utf-8 + +import sqlalchemy +from sqlalchemy import String, Integer, ForeignKey, Time, Date, MetaData, Text, Boolean +from elements import Column, RemovedColumn, Table, Enumeration +import elements +from staticenum import StaticEnum + +metadata = MetaData() +def describe_enums(): + return elements.describe_enums(metadata) + +# Users + +users = Table('users', metadata, 'Utilisateurs', + Column('username', String(250), primary_key=True, label='Nom d\'utilisateur'), + Column('level', StaticEnum('user,maintainer,administrator'), label='Niveau de permissions'), + Column('first_name', String(250), label='Prénom'), + Column('last_name', String(250), label='Nom'), + Column('phone', String(250), label='Téléphone'), + Column('email', String(250), label='E-Mail') +) + +# Playlists + +media_playlists = Table('playlists', metadata, 'Sélections personelles d\'items et de collections', + Column('id', Integer, primary_key='true', label='Identifiant'), + Column('owner_username', String(250), ForeignKey('users.username'), label='Propriétaire'), + Column('name', String(250), label='Intitulé')) + +media_playlist_resources = Table('playlist_resources', metadata, 'Ressources associées aux sélections personelles ', + Column('playlist_id', Integer, ForeignKey('playlists.id'), label='Identifiant de la sélection'), + Column('resource_type', StaticEnum('item', 'collection'), label='Type de ressource (item, collection)'), + Column('resource_id', String(250), label='Identifiant de la ressource') +) + +# Simple enumerations + +physical_formats = Enumeration('physical_formats', metadata, 'Formats physiques', old_name='Format (e)') +publishing_status = Enumeration('publishing_status', metadata, 'Status d\'édition/réédition', old_name='Réédition (e)') +publishers = Enumeration('publishers', metadata, 'Editeurs', old_name='Editeur1 (e)') +acquisition_modes = Enumeration('acquisition_modes', metadata, 'Modes d\'acquisition', old_name='Mode_Acqui (e)') +metadata_authors = Enumeration('record_authors', metadata, 'Rédacteurs des fiches', old_name='Rédacteur_Fiche (e)') +metadata_writers = Enumeration('metadata_writers', metadata, 'Opérateur de saisie des fiches', old_name='Saisie_Fiche (e)') +legal_rights = Enumeration('legal_rights', metadata, 'Statuts juridiques', old_name='Droit_d\'Utiliser (e)') +recording_contexts = Enumeration('recording_contexts', metadata, 'Contextes d\'enregistrement', old_name='Terrain_ou_Autre (e)') +ad_conversions = Enumeration('ad_conversions', metadata, 'Statuts de numérisation', old_name='Numérisation (e)') +ethnic_groups = Enumeration('ethnic_groups', metadata, 'Ethnies/Groupe social', old_name='Ethnie (t)') +vernacular_styles = Enumeration('vernacular_styles', metadata, 'Forme / genre vernaculaire', old_name='Form (t)') +generic_styles = Enumeration('generic_styles', metadata, 'Forme / genre générique', old_name='FormStyle générique (e)') +context_keywords = Enumeration('context_keywords', metadata, 'Mots clés du contexte ethnographique', old_name='Mot_Clef (t)') +publisher_collections = Enumeration('publisher_collections', metadata, 'Collections éditeur', old_name='Collection_Série (e)') + +# Geographic Thesaurus + +location_types = Enumeration('location_types', metadata, 'GeoEthno / Types de lieux') + +locations = Table('locations', metadata, 'GeoEthno / Lieux)', + Column('name', String(127), primary_key=True, label='Terme descripteur'), + Column('type', StaticEnum('country', 'continent', 'other')), + Column('complete_type', location_types), + Column('current_name', String(127), ForeignKey('locations.name'), label='Nom actuel'), + Column('is_authoritative', Boolean), +) + +location_aliases = Table('location_aliases', metadata, 'GeoEthno / Alias des lieux', + Column('location_name', String(127), ForeignKey('locations.name'), primary_key=True), + Column('alias', String(127), primary_key=True), + Column('is_authoritative', Boolean)) + +location_relations = Table('location_relations', metadata, 'GeoEthno / Relations hiérachiques', + Column('location_name', String(127), ForeignKey('locations.name'), primary_key=True), + Column('parent_location_name', String(127), ForeignKey('locations.name'), primary_key=True) +) + +# Media Collections + +media_collections = Table('media_collections', metadata, 'Collections', + Column('reference', + String(250), unique=True, + old_name='Réf', label='Référence'), + Column('physical_format_id', + physical_formats, + old_name='Format', label='Format', + desc="Format du 1er exemplaire archivé"), + Column('old_id', + String(250), + old_name='Cote', label='Ancienne cote'), + Column('id', + String(250), primary_key=True, + dc='identifier', + label='Cote', conversion='à préciser'), + Column('title', + String(250), + dc='title', + old_name='Titre', label='Titre'), + Column('native_title', + String(250), + dc='title', + old_name='Transcrip_Trad', label='Traduction du titre'), + Column('physical_items_num', + Integer, + old_name='Nb_de_pieces', label='Nombre de supports physiques'), + Column('publishing_status_id', + publishing_status, + old_name='Réédition', label='Réédition'), + RemovedColumn(old_name='Original'), + RemovedColumn(old_name='Copie_TotPartie'), + RemovedColumn(old_name='Copié_de'), + Column('creator', + String(250), + dc='creator', + old_name='Auteur_Compil', label='Auteur / Cédant'), + Column('booklet_author', + String(250), + dc='contributor', + old_name='Auteur_Notice', label='Auteur notice'), + Column('booklet_description', + Text, + old_name='Notice', label='Notice / Dossier technique'), + Column('collector', + Text, + dc='contributor', + old_name='Collecteur', label='Collecteur'), + Column('publisher_id', + publishers, + dc='publisher', + old_name='Editeur', label='Editeur', + desc='Pour les documents ÉDITÉS:Nom et État de l\'Editeur. Pour les INÉDITS :voir champ "Type de document".'), + Column('year_published', + Integer, + dc='date', + old_name='Année_parution', label='Année de parution', + desc='Ne concerne que les documents ÉDITÉS.', + conversion='à préciser, traiter les nombres négatifs ?'), + Column('publisher_collection', + publisher_collections, + old_name='Collect_Série', label='Collection éditeur', + comment='faux: nom de la collection, suivi du n° dans la collection.'), + Column('publisher_serial', + String(250), + old_name='Num_Dans_Collec', label='Numéro de série', + desc='Numéro de série dans la collection éditeur', + comment='à valider'), + Column('external_references', + Text, + old_name='Réf_Biblio', label='Bibliographie', + desc='Références biblio/disco/filmographiques, uniquement liées à ce support'), + Column('acquisition_mode_id', + acquisition_modes, + old_name='Mod_Acqui', label='Mode d\'acquisition'), + Column('comment', + Text, + old_name='Commentaire', label='Commentaire'), + Column('metadata_author_id', + metadata_authors, + dc='contributor', + old_name='Rédacteur_Fiche', label='Rédacteur fiche', + desc='Responsable de l\'analyse documentaire'), + Column('metadata_writer_id', + metadata_writers, + old_name='Saisie_Fiche', label='Saisie fiches', + desc='Personne qui a saisi les fiches dans la base de données.'), + Column('legal_rights_id', + legal_rights, + dc='rights', + old_name='Droit_Utiliser', label='Statut juridique'), + Column('alt_ids', + String(250), + old_name='Autres_Cotes', label='Autres exemplaires'), + Column('recorded_from_year', + Integer, + dc='date', + old_name='Année_Enreg', label='Années d\'enregistrement', + conversion="split"), + Column('recorded_to_year', + Integer, + dc='date', + old_name='Année_Enreg', label='Années d\'enregistrement', + conversion="split"), + Column('recording_context_id', + recording_contexts, + old_name='Terrain_ou_Autr', label='Contexte d\'enregistrement'), + Column('approx_duration', + Time(), + old_name='Durée_approx', label='Durée approximative'), + Column('doctype_code', + Integer, + old_name='Tri_DiBm', label='Type de document'), + Column('travail', + String(250), + old_name='Travail', label='?'), + Column('state', + String(250), + old_name='Compil_Face_Plage', label="Etat"), + Column('cnrs_contributor', + String(250), + old_name='Déposant_CNRS', label="Déposant CNRS", + desc='Pour les INÉDITS uniquement. Signale les collectes ayant bénéficées d\'une aide du CNRS.'), + Column('items_done', + String(250), + old_name='Fiches', label='Fiches faîtes', + desc="Signale que les fiches Item de ce support sont présentes dans la base."), + Column('a_informer_07_03', + String(250), + old_name='A informer_07-03', label='?'), + Column('ad_conversion_id', + ad_conversions, + old_name='Numérisation', label="Historique de numérisation"), + RemovedColumn(old_name='Champ36'), +) + +# Media Items + +media_item_context_keywords = Table('media_item_context_keywords', metadata, + 'Mots clés associés à un item', + Column('media_item_id', Integer, ForeignKey('media_items.id')), + Column('context_keyword_id', context_keywords)) + +media_items = Table('media_items', metadata, 'Items', + RemovedColumn(old_name='Réf', comment='Calculé en temps réel à partir de la collection'), + Column('collection_id', + String(250), ForeignKey('media_collections.id'), + dc='relation/isPartOf', + label='Collection'), + RemovedColumn(old_name='Format', comment='Calculé en temps réel à partir de la collection'), + RemovedColumn(old_name='Cote_Support', comment='Calculé en temps réel à partir de la collection'), + Column('track', + String(250), + old_name="Face_Plage", label="N° de l'item"), + Column('id', + String(250), + old_name='Cote_Phono', label="Cote item"), + Column('approx_duration', + Time(), + old_name='Durée', label='Durée'), + Column('recorded_from_date', + Date(), + dc='date', + old_name='Date_enregistr', label='Date', desc='Date de l\'enregistrement'), + Column('recorded_to_date', + Date(), + dc='date', + old_name='Date_enregistr', label='Date'), + Column('location_name', + Integer, ForeignKey('locations.name'), + dc='coverage', + old_name=['Continent', 'Etat', 'Région_Village'], label='Lieu', + desc='(?) Lieu de provenance de la musique. Si le lieu de l\'enregistrement est autre, l\'indiquer en "Remarques".'), + Column('location_comment', + String(250), + old_name='Région_Village', label='Commentaire lieu'), + Column('ethnic_group_id', + ethnic_groups, + old_name='Ethnie_GrSocial', label='Ethnie/Groupe social', comment='attention alias ethnies'), + RemovedColumn(old_name='Titre_Support', comment='Calculé en temps réel à partir de la collection'), + Column('title', + String(250), + dc='title', + old_name='Titre_pièce', label='Titre Item'), + Column('native_title', + String(250), + dc='title', + old_name='Transcrip_Trad', label='Traduction du titre', + desc='Traduction des langues non communes, plus translittération des langues n\'utilisant pas l\'alphabet latin.'), + Column('author', + String(250), + dc='creator', + old_name='Auteur', label='Auteur', + desc='Le cas échéant, faire suivre le nom par une mention "-auteur /-compositeur / -arrangeur"'), + Column('vernacular_style_id', + vernacular_styles, + old_name='Form_Genr_Style', label='Forme / genre vernaculaire [nom à revoir]', + desc='Nom local de la forme ou du genre'), + RemovedColumn(old_name='Struct_Modale'), + RemovedColumn(old_name='Struct_Rythm'), + RemovedColumn(old_name='Struct_Rythm'), + RemovedColumn(old_name='Fonction_Usage', + comment='Champ inutile, les mots clés sont associés via une table de relation externe'), + Column('context_comment', + Text, + old_name='Comm_FonctUsage', label='Contexte ethnographique : commentaires'), + Column('external_references', + String(250), + old_name='Documentation', label='Références', + desc='Références directement liées à l\'item.'), + Column('moda_execut', + String(250), + old_name='Moda_Execut', comment='à supprimer ?'), + Column('copied_from_item_id', + String(250), ForeignKey('media_items.id'), + dc='relation/isVersionOf', + old_name='Copie_de', label='Copie de'), + Column('collector', + String(250), + dc='contributor', + old_name='Enregistré_par', label='Collecteur'), + Column('cultural_area', + String(250), + old_name='Aire culturelle', label='Aire culturelle'), + RemovedColumn(old_name='Année_Enreg', + comment='calculé en temps-réel à partir de la date d\'enregistrement'), + Column('generic_style', + generic_styles, + old_name='FormStyl généri', label='Forme / genre générique'), + Column('collector_selection', + String(250), + old_name='ChoixCollecteur', label='Choix du collecteur', + desc='Permet au collecteur de repérer les items les plus intéressants'), + RemovedColumn(old_name='Repère_bande'), + Column('creator_reference', + String(250), + old_name='NroBandNroPièc', label='Référence du déposant'), +) + + + + + + + + + + + + + + + + + diff --git a/trunk/docref/spec/texttable.py b/trunk/docref/spec/texttable.py new file mode 100644 index 0000000..3d07d25 --- /dev/null +++ b/trunk/docref/spec/texttable.py @@ -0,0 +1,155 @@ +#coding: utf-8 +import cStringIO,operator + +def indent(rows, hasHeader=False, headerChar=u'-', delim=u' | ', justify=u'left', + separateRows=False, prefix=u'', postfix=u'', wrapfunc=lambda x:x): + """Indents a table by column. + - rows: A sequence of sequences of items, one sequence per row. + - hasHeader: True if the first row consists of the columns' names. + - headerChar: Character to be used for the row separator line + (if hasHeader==True or separateRows==True). + - delim: The column delimiter. + - justify: Determines how are data justified in their column. + Valid values are 'left','right' and 'center'. + - separateRows: True if rows are to be separated by a line + of 'headerChar's. + - prefix: A string prepended to each printed row. + - postfix: A string appended to each printed row. + - wrapfunc: A function f(text) for wrapping text; each element in + the table is first wrapped by this function.""" + # closure for breaking logical rows to physical, using wrapfunc + def rowWrapper(row): + newRows = [wrapfunc(item).split('\n') for item in row] + return [[substr or '' for substr in item] for item in map(None,*newRows)] + # break each logical row into one or more physical ones + logicalRows = [rowWrapper(row) for row in rows] + # columns of physical rows + columns = map(None,*reduce(operator.add,logicalRows)) + # get the maximum of each column by the string length of its items + maxWidths = [max([len(item) for item in column]) for column in columns] + rowSeparator = u"+" + u"+".join([u'-' * (width + len(delim) - 1) for width in maxWidths]) + u"+" + headerSep = u"+" + u"+".join([u'=' * (width + len(delim) - 1) for width in maxWidths]) + u"+" + #headerChar * (len(prefix) + len(postfix) + sum(maxWidths) + \ + # len(delim)*(len(maxWidths)-1)) + #headerSep = u"=" * (len(prefix) + len(postfix) + sum(maxWidths) + \ + # len(delim)*(len(maxWidths)-1)) + # select the appropriate justify method + #justify = {'center':str.center, 'right':str.rjust, 'left':str.ljust}[justify.lower()] + output=u'' + if separateRows: + output += rowSeparator + "\n" + + for physicalRows in logicalRows: + for row in physicalRows: + output += \ + prefix \ + + delim.join([item.ljust(width) for (item,width) in zip(row,maxWidths)]) \ + + postfix + "\n" + if hasHeader: output += headerSep + "\n"; hasHeader=False + elif separateRows: output += rowSeparator + "\n" + return output + +# written by Mike Brown +# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/148061 +def wrap_onspace(text, width): + """ + A word-wrap function that preserves existing line breaks + and most spaces in the text. Expects that existing line + breaks are posix newlines (\n). + """ + return reduce(lambda line, word, width=width: '%s%s%s' % + (line, + ' \n'[(len(line[line.rfind('\n')+1:]) + + len(word.split('\n',1)[0] + ) >= width)], + word), + text.split(' ') + ) + +import re +def wrap_onspace_strict(text, width): + """Similar to wrap_onspace, but enforces the width constraint: + words longer than width are split.""" + wordRegex = re.compile(r'\S{'+str(width)+r',}') + return wrap_onspace(wordRegex.sub(lambda m: wrap_always(m.group(),width),text),width) + +import math +def wrap_always(text, width): + """A simple word-wrap function that wraps text on exactly width characters. + It doesn't split the text in words.""" + return '\n'.join([ text[width*i:width*(i+1)] \ + for i in xrange(int(math.ceil(1.*len(text)/width))) ]) + +if __name__ == '__main__': + labels = ('First Name', 'Last Name', 'Age', 'Position') + data = \ + '''John,Smith,24,Software Engineer + Mary,Brohowski,23,Sales Manager + Aristidis,Papageorgopoulos,28,Senior Reseacher''' + rows = [row.strip().split(',') for row in data.splitlines()] + + print 'Without wrapping function\n' + print indent([labels]+rows, hasHeader=True) + # test indent with different wrapping functions + width = 10 + for wrapper in (wrap_always,wrap_onspace,wrap_onspace_strict): + print 'Wrapping function: %s(x,width=%d)\n' % (wrapper.__name__,width) + print indent([labels]+rows, hasHeader=True, separateRows=True, + prefix='| ', postfix=' |', + wrapfunc=lambda x: wrapper(x,width)) + + # output: + # + #Without wrapping function + # + #First Name | Last Name | Age | Position + #------------------------------------------------------- + #John | Smith | 24 | Software Engineer + #Mary | Brohowski | 23 | Sales Manager + #Aristidis | Papageorgopoulos | 28 | Senior Reseacher + # + #Wrapping function: wrap_always(x,width=10) + # + #---------------------------------------------- + #| First Name | Last Name | Age | Position | + #---------------------------------------------- + #| John | Smith | 24 | Software E | + #| | | | ngineer | + #---------------------------------------------- + #| Mary | Brohowski | 23 | Sales Mana | + #| | | | ger | + #---------------------------------------------- + #| Aristidis | Papageorgo | 28 | Senior Res | + #| | poulos | | eacher | + #---------------------------------------------- + # + #Wrapping function: wrap_onspace(x,width=10) + # + #--------------------------------------------------- + #| First Name | Last Name | Age | Position | + #--------------------------------------------------- + #| John | Smith | 24 | Software | + #| | | | Engineer | + #--------------------------------------------------- + #| Mary | Brohowski | 23 | Sales | + #| | | | Manager | + #--------------------------------------------------- + #| Aristidis | Papageorgopoulos | 28 | Senior | + #| | | | Reseacher | + #--------------------------------------------------- + # + #Wrapping function: wrap_onspace_strict(x,width=10) + # + #--------------------------------------------- + #| First Name | Last Name | Age | Position | + #--------------------------------------------- + #| John | Smith | 24 | Software | + #| | | | Engineer | + #--------------------------------------------- + #| Mary | Brohowski | 23 | Sales | + #| | | | Manager | + #--------------------------------------------- + #| Aristidis | Papageorgo | 28 | Senior | + #| | poulos | | Reseacher | + #--------------------------------------------- + diff --git a/trunk/docref/tools/analyse_collection_ids.py b/trunk/docref/tools/analyse_collection_ids.py new file mode 100644 index 0000000..d180f55 --- /dev/null +++ b/trunk/docref/tools/analyse_collection_ids.py @@ -0,0 +1,150 @@ +import MySQLdb +import _mysql_exceptions +import re +from sys import stdout + +""" +CREATE TABLE `coll` ( + `cote` varchar(255) default NULL, + `format` varchar(255) default NULL, + `regex` varchar(255) default NULL, + `new_id` varchar(64) default NULL, + `dup` BOOLEAN NOT NULL, + UNIQUE KEY `new_id` (`new_id`), + UNIQUE KEY `cote` (`cote`) +) +""" + + +collection_patterns = [ + { 'format': 'BM.aaa.nnn.mmm', 'regex': r'^(BM)\.([0-9]{3})\.([0-9]{3})\.([0-9]{3})$'}, + { 'format': 'BM.aaaa.nnn.mmm/pp', 'regex': r'^(BM)\.([0-9]{4})\.([0-9]{3})\.([0-9]{3})/[0-9]{2}$'}, + { 'format': 'BM.aaaa.nnn.mmm', 'regex': r'^(BM)\.([0-9]{4})\.([0-9]{3})\.([0-9]{3})$'}, + { 'format': 'BM.aaaa.nnn.mmm/', 'regex': r'^(BM)\.([0-9]{4})\.([0-9]{3})\.([0-9]{3})/$'}, + { 'format': 'BM.aaaa.nnn.mmm/ppp', 'regex': r'^(BM)\.([0-9]{4})\.([0-9]{3})\.([0-9]{3})/[0-9]{3}$'}, + { 'format': 'BM.aaaa.nnn.mm/pp', 'regex': r'^(BM)\.([0-9]{4})\.([0-9]{3})\.([0-9]{2})/[0-9]{2}$'}, + { 'format': 'BM.aaaa.nnn', 'regex': r'^(BM)\.([0-9]{4})\.([0-9]{3})$'}, + { 'format': 'BM.aaa.nnn.mmm/pp', 'regex': r'^(BM)\.([0-9]{3})\.([0-9]{3})\.([0-9]{3})/[0-9]{2}$'}, + { 'format': 'BM.aaa.nnn FANTOME', 'regex': r'^(BM)\.([0-9]{3})\.([0-9]{3}) FANTOME$'}, + { 'format': 'BM.aaa.nnn', 'regex': r'^(BM)\.([0-9]{3})\.([0-9]{3})$'}, + { 'format': 'BM.aaa.nnnBISoo/pp', 'regex': r'^(BM)\.([0-9]{3})\.([0-9]{3})BIS([0-9]{2})/[0-9]{2}$'}, + { 'format': 'BM.aaa.nnn.mmm.ppp', 'regex': r'^(BM)\.([0-9]{3})\.([0-9]{3})\.([0-9]{3})\.[0-9]{3}$'}, + { 'format': 'BM.aaa.nnn.mmm/ppp', 'regex': r'^(BM)\.([0-9]{3})\.([0-9]{3})\.([0-9]{3})/[0-9]{3}$'}, + { 'format': 'BM.aaa.nnn/pp', 'regex': r'^(BM)\.([0-9]{3})\.([0-9]{3})/[0-9]{2}$'}, + { 'format': 'BM.aaa.nnn-BIS.ooo/pp', 'regex': r'^(BM)\.([0-9]{3})\.([0-9]{3})-BIS\.([0-9]{3})/[0-9]{2}$'}, + { 'format': 'BM.aaaa.nnn.mmm/NN', 'regex': r'^(BM)\.([0-9]{4})\.([0-9]{3})\.([0-9]{3})/NN$'}, + { 'format': 'BM.aaa.nnn.mmm/pp-DEPOT', 'regex': r'^(BM)\.([0-9]{3})\.([0-9]{3})\.([0-9]{3})/[0-9]{2}-DEPOT$'}, + { 'format': 'BM.aaa.nnn.mmm-o>p', 'regex': r'^(BM)\.([0-9]{3})\.([0-9]{3})\.([0-9]{3})-[0-9]>[0-9]$'}, + { 'format': 'CY.aaaa.nnn', 'regex': r'^(CY)\.([0-9]{4})\.([0-9]{3})$'}, + { 'format': 'DI.aaaa.nnn.mmm', 'regex': r'^(DI)\.([0-9]{4})\.([0-9]{3})\.([0-9]{3})$'}, + { 'format': 'DI.aaaa.nnn.mmm/pp', 'regex': r'^(DI)\.([0-9]{4})\.([0-9]{3})\.([0-9]{3})/[0-9]{2}$'}, + { 'format': 'DI.aaa.nnn.mmm', 'regex': r'^(DI)\.([0-9]{3})\.([0-9]{3})\.([0-9]{3})$'}, + { 'format': 'DI.aaa.nnn.mmm/pp', 'regex': r'^(DI)\.([0-9]{3})\.([0-9]{3})\.([0-9]{3})/[0-9]{2}$'}, + { 'format': 'DI.aaa.nnn.mmm-o/p', 'regex': r'^(DI)\.([0-9]{3})\.([0-9]{3})\.([0-9]{3})-[0-9]/[0-9]$'}, + { 'format': 'FANTOME 2*', 'regex': r'FANTOME 2\*$'}, +] + +db = MySQLdb.connect(user='root', db='test'); + +rcursor = db.cursor() +wcursor = db.cursor() + +wcursor.execute("UPDATE coll SET format='', new_id = NULL, dup = 0") + +nrow = 0 +for pattern in collection_patterns: + stdout.write('* format: ' + pattern['format'] + '\n') + wcursor.execute("UPDATE coll SET format=%s WHERE cote REGEXP %s", + (pattern['format'], pattern['regex'])) + rcursor.execute("SELECT COUNT(*) FROM coll") + row = rcursor.fetchone() + count = row[0] + rcursor.execute("SELECT cote FROM coll WHERE cote REGEXP %s", (pattern['regex'],)) + row = rcursor.fetchone() + while row: + if nrow % 200 == 0: + stdout.write(" row " + str(nrow) + "/" + str(count) + '\n') + id = row[0] + match = re.match(pattern['regex'], id) + + published = False + year = -1 + serial = -1 + physical = -1 + + if (match.lastindex >= 1): + published = (match.group(1) == 'DI') + if (match.lastindex >= 2): + year = int(match.group(2)) + if (match.lastindex >= 3): + serial = int(match.group(3)) + if (match.lastindex >= 4): + physical = int(match.group(4)) + + if (year == -1 or serial == -1): + stdout.write(' missing year or serial: ' + id + '\n') + else: + tokens = [] + if published: + tokens.append('CNRSMH_E') + else: + tokens.append('CNRSMH_I') + + if year < 1000: + if year < 100: + year += 2000 + else: + year += 1000 + tokens.append(str(year)) + + tokens.append(str(serial).rjust(3, '0')) + + if published: + if physical != -1: + tokens.append(str(physical).rjust(3, '0')) + else: + tokens.append('001') + + new_id = '_'.join(tokens) + + try: + wcursor.execute("UPDATE coll SET new_id = %s WHERE cote = %s", (new_id, id)) + except _mysql_exceptions.IntegrityError, (errno, errstr): + if errno == 1062: + stdout.write(' duplicate entry: ' + id + ' -> ' + new_id + '\n') + wcursor.execute("UPDATE coll SET dup = 1 WHERE cote = %s", (id,)) + else: + raise + + row = rcursor.fetchone() + nrow += 1 + +rcursor.execute("SELECT format, cote, COUNT(*), SUM(dup) FROM coll GROUP BY format"); + +stdout.write("\nFORMAT STATS:\n") +row = rcursor.fetchone() +stdout.write("format\texample\tcount\tduplicates\n"); +while row: + stdout.write(row[0] + "\t" + row[1] + "\t" + str(row[2]) + "\t" + str(row[3]) + '\n') + row = rcursor.fetchone() + +rcursor.execute("SELECT cote FROM coll WHERE new_id IS NULL AND dup = 1") +stdout.write("\nUNCONVERTED IDs (duplicates):\n") +row = rcursor.fetchone() +while row: + stdout.write(row[0] + '\n') + row = rcursor.fetchone() + +rcursor.execute("SELECT cote FROM coll WHERE new_id IS NULL AND dup = 0") +stdout.write("\nUNCONVERTED IDs (non duplicates):\n") +row = rcursor.fetchone() +while row: + stdout.write(row[0] + '\n') + row = rcursor.fetchone() + + + + + + + diff --git a/trunk/import/README b/trunk/import/README new file mode 100644 index 0000000..7b6f193 --- /dev/null +++ b/trunk/import/README @@ -0,0 +1,13 @@ + +========================================== +CREM data import instructions and programs +========================================== + +* ``prototype`` : this directory contains scripts to perform an experimental + import of the CREM database into Telemeta 0.3.x. It is only meant as a + proof of concept. +* ``raw_conversion`` : instructions and scripts to perform a full raw conversion + of the CREM database from 4D to MySQL. The result has the same structure + as the original 4D database, and, as such, can't be used directly in + Telemeta. + diff --git a/trunk/import/prototype/README b/trunk/import/prototype/README new file mode 100644 index 0000000..88c4a14 --- /dev/null +++ b/trunk/import/prototype/README @@ -0,0 +1,37 @@ +================================================== +CREM data and how to import it into Telemeta 0.3.x +================================================== + +Warning: the following instructions allow you to import the CREM's data +into telemeta. However, it is currently a rather data destructive process, +only meant for demonstration and testing purpose. Do not use this in a +production environment. + +1. Install Telemeta upon MySQL. Initialize the database using Telemeta's + Django models. Ensure that everything is running fine before going any + further. + +2. Run prepare on the source directory. The source directory must contain + text files as they were exported from the 4D database. These files are + expected to be gzipped. + + Example:: + + $ scripts/prepare src/2007-05-09 + +3. Use the import.sql script to insert the data into your MySQL database. + + Example:: + + $ mysql your_telemeta_database < scripts/import.sql + +4. Copy the WAV test file of your choice, into /items/test.wav + This single file is associated with all media items, for testing purpose. + +That should be it. If you want to run Telemeta against SQLite instead of +MySQL, first follow the above instructions to import the data into MySQL. +Then convert your data from MySQL to SQLite, this is a common task, google +about it. + + + diff --git a/trunk/import/prototype/scripts/import.sql b/trunk/import/prototype/scripts/import.sql new file mode 100644 index 0000000..0bb05be --- /dev/null +++ b/trunk/import/prototype/scripts/import.sql @@ -0,0 +1,31 @@ +DELETE FROM telemeta_collection; +LOAD DATA INFILE '/tmp/crem_import/support.txt' INTO TABLE telemeta_collection +FIELDS TERMINATED BY '\t' +LINES TERMINATED BY '\r\n'; + +UPDATE telemeta_collection SET id=REPLACE(id, '/', '--'); +UPDATE telemeta_collection SET copied_from_id = NULL WHERE copied_from_id = ''; + +DELETE FROM telemeta_item; +LOAD DATA INFILE '/tmp/crem_import/phono.txt' INTO TABLE telemeta_item +FIELDS TERMINATED BY '\t' +LINES TERMINATED BY '\r\n'; + +UPDATE telemeta_item SET id=REPLACE(id, ":", "__"); +UPDATE telemeta_item SET id=REPLACE(id, '/', '--'); +UPDATE telemeta_item SET id=REPLACE(id, '?', 'i'); +UPDATE telemeta_item SET collection_id=REPLACE(collection_id, '/', '--'); +UPDATE telemeta_item SET title='' WHERE title='N'; +UPDATE telemeta_item SET etat=REPLACE(etat, ')', '_'); +UPDATE telemeta_item SET etat=REPLACE(etat, '(', '_'); +UPDATE telemeta_item SET file="items/test.wav"; + +DELETE FROM telemeta_physicalformat; +INSERT INTO telemeta_physicalformat (value) + SELECT DISTINCT physical_format FROM telemeta_collection + WHERE physical_format <> '' AND physical_format IS NOT NULL; + +DELETE FROM telemeta_publishingstatus; +INSERT INTO telemeta_publishingstatus (value) + SELECT DISTINCT publishing_status FROM telemeta_collection + WHERE publishing_status <> '' AND publishing_status IS NOT NULL; diff --git a/trunk/import/prototype/scripts/prepare b/trunk/import/prototype/scripts/prepare new file mode 100755 index 0000000..92a7618 --- /dev/null +++ b/trunk/import/prototype/scripts/prepare @@ -0,0 +1,43 @@ +#!/bin/bash + +if [ "$1" == "" ] +then + echo "Please provide the source directory" + exit 1 +fi + +src=$1 +tmpdir=crem_import +required="support.txt.gz phono.txt.gz" + +for f in $required +do + if ! [ -f $src/$f ] + then + echo "Can't find $f in $src" + exit 1 + fi +done + +if [ -d /tmp/$tmpdir ] +then + rm /tmp/$tmpdir/* +else + mkdir /tmp/$tmpdir +fi + +echo -n "Converting charset and cleaning text files.. " + +zcat $src/support.txt.gz | tail -n +2 \ + | sed 's/^ *//' | sed 's/ *\t */\t/g'| sed 's/ *$//' \ + | iconv -f WINDOWS-1252 -c -t latin1 \ + > /tmp/$tmpdir/support.txt + +zcat $src/phono.txt.gz | tail -n +2 \ + | sed 's/^ *//' | sed 's/ *\t */\t/g'| sed 's/ *$//' \ + | iconv -f WINDOWS-1252 -c -t latin1 | sed '/^\t/d' \ + > /tmp/$tmpdir/phono.txt + +echo "Done" + + diff --git a/trunk/import/prototype/src/2007-05-09/phono.txt.gz b/trunk/import/prototype/src/2007-05-09/phono.txt.gz new file mode 100755 index 0000000..fd0be4a Binary files /dev/null and b/trunk/import/prototype/src/2007-05-09/phono.txt.gz differ diff --git a/trunk/import/prototype/src/2007-05-09/support.txt.gz b/trunk/import/prototype/src/2007-05-09/support.txt.gz new file mode 100755 index 0000000..a7ec8c6 Binary files /dev/null and b/trunk/import/prototype/src/2007-05-09/support.txt.gz differ diff --git a/trunk/import/raw_conversion/README b/trunk/import/raw_conversion/README new file mode 100644 index 0000000..17f2195 --- /dev/null +++ b/trunk/import/raw_conversion/README @@ -0,0 +1,43 @@ +========================================================== +Base de données du CREM : conversion brut de 4D vers MySQL +========================================================== + +Le présent document décrit la procédure de conversion brut de la base de +données du CREM de 4D vers MySQL. La base MySQL obtenue a la même structure +que la base originale 4D. + +Cette procédure doit être effectuée par un informaticien. + +Les instructions ci-dessous nécessitent l'emploi de la version 6.5.x de 4D pour +Windows. + +Avertissement: il est fortement recommandé de réaliser ces opérations sur une +copie de la base 4D, et non sur la version de production. + +1. Sur un poste Windows où se trouve la base du CREM, et équipé de 4D 6.5.x, + créer le répertoire C:\export_crem + +2. Lancer 4D, ouvrir la base du CREM, créer une nouvelle méthode 4D avec + le code source fourni dans le fichier ``export.4d.txt``, et lancer cette + méthode de façon à exporter toute la base et les relations dans le + répertoire C:\export_crem + + Cette opération peut prendre plusieurs minutes. Une fenêtre "Export terminé" + s'affiche à la fin. + + Remarque: si vous utilisez une version de démonstration de 4D, vous ne pouvez + pas créer de nouvelle méthode, mais vous pouvez remplacer une méthode existante. + +3. Placer le répertoire export_crem sur un poste linux, de façon à ce qu'il soit + accessible à l'import MySQL, par exemple dans /tmp/export_crem avec 777 pour + permissions + +4. Créer une base MySQL, par exemple: crem + +5. Importer la toutes les données dans la base MySQL avec la commande:: + + ./import /tmp/export_crem | mysql -vvv crem + + Vérifiez que chaque requête se termine par "Query OK" avec "Warnings: 0", + pour vous assurer du bon déroulement de l'opération. + diff --git a/trunk/import/raw_conversion/export.4d.txt b/trunk/import/raw_conversion/export.4d.txt new file mode 100755 index 0000000..bd30cd6 --- /dev/null +++ b/trunk/import/raw_conversion/export.4d.txt @@ -0,0 +1,187 @@ +`Export de toutes les tables + +C_ALPHA(1;$fieldDelimiter;$recordDelimiter) +C_ALPHA(32;$tableName;$fieldName) +C_ENTIER LONG($numberOfTables;$tableNumber;$numberOfFields;$fieldNumber) +C_ENTIER LONG($numberOfRecords;$fieldType) +C_POINTEUR($tablePtr;$fieldPtr) +C_TEXTE($fieldValue) +C_HEURE($documentReference) +C_REEL($Plateforme) +PROPRIETES PLATE FORME($Plateforme) + +$fieldDelimiter:=Caractere(9)   +$recordDelimiter:=Caractere(10)   + +$numberOfTables:=Nombre de tables   + +Boucle ($tableNumber;1;$numberOfTables)   + + $tablePtr:=Table($tableNumber)   + $tableName:=Nom de la table($tableNumber)   + + $documentReference:=Creer document("C:\export_crem\"+$tableName+".txt";"TEXT")   + + Si (OK=1)   + $numberOfFields:=Nombre de champs($tableNumber)   + + Boucle ($fieldNumber;1;$numberOfFields)   + $fieldName:=Nom du champ($tableNumber;$fieldNumber)   + Si ($fieldNumber#$numberOfFields)   + Si ($Plateforme=Windows ) + ENVOYER PAQUET($documentReference;Mac vers Windows($fieldName)+$fieldDelimiter) +    + Sinon + ENVOYER PAQUET($documentReference;$fieldName+$fieldDelimiter) +    + Fin de si + Sinon + Si ($plateforme=Windows ) + ENVOYER PAQUET($documentReference;Mac vers Windows($fieldName)+$recordDelimiter) +    + Sinon + ENVOYER PAQUET($documentReference;$fieldName+$recordDelimiter) +    + Fin de si + Fin de si + Fin de boucle + + TOUT SELECTIONNER($tablePtr->)   + $numberOfRecords:=Enregistrements trouves($tablePtr->)   + + Boucle ($recordNumber;1;$numberOfRecords)   + + Boucle ($fieldNumber;1;$numberOfFields)   + + $fieldPtr:=Champ($tableNumber;$fieldNumber)   + PROPRIETES CHAMP($fieldPtr;$fieldType)   + +    + + Au cas ou + : (($fieldType=Est un numérique ) | ($fieldType=Est un entier ) | ($fieldType=Est un entier long )) + $fieldValue:=Chaine($fieldPtr->)   + : ($fieldType=Est une date ) + $fieldValue:=Chaine($fieldPtr->;7)   + : ($fieldType=Est une heure ) + $fieldValue:=Chaine($fieldPtr->;1)   + : ($fieldType=Est un booléen ) + +    + + $fieldValue:=Chaine(Num($fieldPtr->);"VRAI;;FAUX")   + : ($fieldType=Est une image ) + $fieldValue:="Image non exportée" + : ($fieldType=Est un BLOB ) + $fieldValue:="BLOB non exporté" + : ($fieldType=Est une sous table ) + $fieldValue:="Sous-table non exportée" + Sinon    + $fieldValue:=$fieldPtr->   + $fieldValue:=Remplacer chaine ($fieldValue; $fieldDelimiter; " ") + $fieldValue:=Remplacer chaine ($fieldValue; $recordDelimiter; " ") + $fieldValue:=Remplacer chaine ($fieldValue; Caractere(13); " ") + Fin de cas + + Si ($fieldNumber#$numberOfFields)   + Si ($Plateforme=Windows ) + ENVOYER PAQUET($documentReference;Mac vers Windows($fieldValue)+$fieldDelimiter)   + Sinon + ENVOYER PAQUET($documentReference;$fieldValue+$fieldDelimiter)   + Fin de si + Sinon + Si ($Plateforme=Windows ) + ENVOYER PAQUET($documentReference;Mac vers Windows($fieldValue)+$recordDelimiter)   +    + Sinon + ENVOYER PAQUET($documentReference;$fieldValue+$recordDelimiter)   +    + Fin de si + + Fin de si + + Fin de boucle + + ENREGISTREMENT SUIVANT($tablePtr->)   + Fin de boucle + + FERMER DOCUMENT($documentReference)   + CHANGER CREATEUR DOCUMENT(Document;"TEXT") + + Fin de si + +Fin de boucle + +`Export des relations des formations + +$tab:=Caractere(9) +$fin:=Caractere(10) +$ret:=Caractere(13) + +$doc:=Creer document("c:\export_crem\Formation.txt";"TXT") +Si (ok=1) + $texte:="Cote_Phono"+$tab+"Instr_Scientif"+$tab+"Instr_Vernacul"+$tab+"Interprète"+$tab+"Total_Instrum"+$fin + ENVOYER PAQUET($doc;Mac vers Windows($texte)) + TOUT SELECTIONNER([Phono]) + Boucle ($i;1;Enregistrements trouves([Phono])) + $cote:=[Phono]Cote_Phono + $cote:=Remplacer chaine($cote; $tab; " ") + $cote:=Remplacer chaine($cote; $fin; " ") + $cote:=Remplacer chaine($cote; $ret; " ") + TOUS LES SOUS ENREGISTREMENTS([Phono]Formation) + Boucle ($j;1;Sous enregistrements trouves([Phono]Formation) + $instr_scientif:=Remplacer chaine([Phono]Formation'Instr_Scientif; $tab; " ") + $instr_scientif:=Remplacer chaine($instr_scientif; $fin; " ") + $instr_scientif:=Remplacer chaine($instr_scientif; $ret; " ") + $instr_vernacul:=Remplacer chaine([Phono]Formation'Instr_Vernacul; $tab; " ") + $instr_vernacul:=Remplacer chaine($instr_vernacul; $fin; " ") + $instr_vernacul:=Remplacer chaine($instr_vernacul; $ret; " ") + $interprete:=Remplacer chaine([Phono]Formation'Interprète; $tab; " ") + $interprete:=Remplacer chaine($interprete; $fin; " ") + $interprete:=Remplacer chaine($interprete; $ret; " ") + $total:=Remplacer chaine([Phono]Formation'Total_Instrum; $tab; " ") + $total:=Remplacer chaine($total; $fin; " ") + $total:=Remplacer chaine($total; $ret; " ") + $texte:=$cote+$tab+$instr_scientif+$tab+$instr_vernacul+$tab+$interprete+$tab+$total+$fin + ENVOYER PAQUET($doc;Mac vers Windows($texte)) + SOUS ENREGISTREMENT SUIVANT([Phono]Formation) + Fin de boucle + LIBERER ENREGISTREMENT([Phono]) + ENREGISTREMENT SUIVANT([Phono]) + Fin de boucle + + FERMER DOCUMENT($doc) + +Fin de si + +`Export des relations des mots clés + +$doc:=Creer document("c:\export_crem\Fonction_Usage.txt";"TXT") +Si (ok=1) + $texte:="Cote_Phono"+$tab+"Mot_Clef"+$fin + ENVOYER PAQUET($doc;Mac vers Windows($texte)) + TOUT SELECTIONNER([Phono]) + Boucle ($i;1;Enregistrements trouves([Phono])) + $cote:=[Phono]Cote_Phono + $cote:=Remplacer chaine($cote; $tab; " ") + $cote:=Remplacer chaine($cote; $fin; " ") + $cote:=Remplacer chaine($cote; $ret; " ") + TOUS LES SOUS ENREGISTREMENTS([Phono]Fonction_Usage) + Boucle ($j;1;Sous enregistrements trouves([Phono]Fonction_Usage) + $mot_clef:=Remplacer chaine([Phono]Fonction_Usage'Mot_Clef; $tab; " ") + $mot_clef:=Remplacer chaine($mot_clef; $fin; " ") + $mot_clef:=Remplacer chaine($mot_clef; $ret; " ") + $texte:=$cote+$tab+$mot_clef+$fin + ENVOYER PAQUET($doc;Mac vers Windows($texte)) + SOUS ENREGISTREMENT SUIVANT([Phono]Fonction_Usage) + Fin de boucle + LIBERER ENREGISTREMENT([Phono]) + ENREGISTREMENT SUIVANT([Phono]) + Fin de boucle + + FERMER DOCUMENT($doc) + +Fin de si + + +ALERTE("Export terminé.") diff --git a/trunk/import/raw_conversion/import b/trunk/import/raw_conversion/import new file mode 100755 index 0000000..a020f39 --- /dev/null +++ b/trunk/import/raw_conversion/import @@ -0,0 +1,50 @@ +#!/bin/bash + +function extract_enum +{ + to_table=$1 + from_table=$2 + from_field=$3 + echo "DROP TABLE IF EXISTS \`$to_table\`;" + echo "CREATE TABLE \`$to_table\` (value TEXT NOT NULL) CHARSET=latin1;" + echo "INSERT INTO \`$to_table\` SELECT DISTINCT \`$from_field\` FROM \`$from_table\` WHERE \`$from_field\` <> '';"; +} + +src=$1 +cd $src + +echo "SET NAMES 'latin1';" +echo + +chmod o+r *.txt + +ls *.txt | while read filename +do + table=$(echo $filename | sed 's/.txt//') + echo "DROP TABLE IF EXISTS \`$table\`;" + echo "CREATE TABLE \`$table\` (" + head -n1 $filename | tr '\t' '\n' | head -n-1 | sed 's/^/ `/' | sed 's/$/` TEXT NOT NULL,/' + head -n1 $filename | tr '\t' '\n' | tail -n1 | sed 's/^/ `/' | sed 's/$/` TEXT NOT NULL/' + echo ") CHARSET=latin1;" + echo + echo "LOAD DATA INFILE '$src/$filename'" + echo " INTO TABLE \`$table\`" + echo " CHARACTER SET 'latin1'" + echo " FIELDS TERMINATED BY '\t' ESCAPED BY '' LINES TERMINATED BY '\n'" + echo " IGNORE 1 LINES;" + echo "SHOW WARNINGS;" + echo +done + +extract_enum Format Support Format +extract_enum Réédition Support Réédition +extract_enum Mode_Acqui Support Mode_Acqui +extract_enum Rédacteur_Fiche Support Rédacteur_Fiche +extract_enum Saisie_Fiche Support Saisie_Fiche +extract_enum Droit_Utiliser Support Droit_Utiliser +extract_enum Terrain_ou_Autr Support Terrain_ou_Autr +extract_enum Numérisation Support Numérisation +extract_enum "FormStyl généri" Phono "FormStyl généri" +extract_enum Editeur1 Support Editeur +extract_enum Collection_Serie Support Collect_Série +