Mappeur

Mappeurs

Les Mappeurs sont les classes ConnectorUnit responsables de la transformation d’un enregistrement externe vers un enregistrement OpenERP et vice versa.

class connector.unit.mapper.ExportMapChild(connector_env)[source]

Bases : connector.unit.mapper.MapChild

MapChild pour les exports

class connector.unit.mapper.ExportMapper(connector_env)[source]

Bases : connector.unit.mapper.Mapper

Mapper pour les exports.

Transforme un enregistrement depuis OpenERP vers un enregistrement du backend

class connector.unit.mapper.ImportMapChild(connector_env)[source]

Bases : connector.unit.mapper.MapChild

MapChild pour les imports

format_items(items_values)[source]

Formate les valeurs des items mappés depuis les Mappeurs enfants.

Il peut être surchargé par exemple pour ajouter les commandes de relation d’OpenERP (6, 0, [IDs]), …

Par exemple, il peut être modifié pour pour gérer la mise à jour d’items existants : vérifier si un “id” a bien été défini par get_item_values() puis utilise la commande (1, ID, {valeurs})

Paramètres:items_values (list) – liste des valeurs pour les items à créer
class connector.unit.mapper.ImportMapper(connector_env)[source]

Bases : connector.unit.mapper.Mapper

Mapper pour les imports.

Transforme un enregistrement depuis un backend vers un enregistrement OpenERP

class connector.unit.mapper.MapChild(connector_env)[source]

Bases : connector.connector.ConnectorUnit

MapChild est responsable de la conversion des items.

Les items sont des sous-enregistrements d’un enregistrement principal. Dans cet exemple, les items sont les enregistrements qui sont dans lines

sales = {'name': 'SO10',
         'lines': [{'product_id': 1, 'quantity': 2},
                   {'product_id': 2, 'quantity': 2}]}

Un MapChild est toujours appelé depuis un autre Mapper qui fournit une configuration children.

Compte tenu de l’exemple ci-dessus, le Mapper « principal » renverrait quelque chose comme ça

{'name': 'SO10',
         'lines': [(0, 0, {'product_id': 11, 'quantity': 2}),
                   (0, 0, {'product_id': 12, 'quantity': 2})]}

Un MapChild est responsable de :

  • Trouver le Mapper pour convertir les items
  • Éventuellement exclure certaines lignes (en surchargeant skip_item())
  • Convertir les enregistrements des items en utilisant le Mapper trouvé
  • Formater les valeurs de sortie vers le format attendu par OpenERP ou par le backend (comme vu ci-dessus avec (0, 0, {values})

Un MapChild peut être étendu comme toute autre ConnectorUnit. Cependant il n’est pas nécessaire de créer un MapChild pour chaque mappeur enfant, ceux par défaut seront utilisés (ImportMapChild ou ExportMapChild).

L’implémentation par défaut ne gère pas les mises à jour : si j’importe une commande deux fois, les lignes seront dupliquées. Ceci n’est pas un problème à condition qu’un import ne prenne en charge que la création (typique pour les commandes). Il peut être implémenté au cas par cas en héritant de get_item_values() et format_items().

format_items(items_values)[source]

Formate les valeurs des items mappés depuis les Mappeurs enfants.

Il peut être surchargé par exemple pour ajouter les commandes de relation d’OpenERP (6, 0, [IDs]), …

Par exemple, il peut être modifié pour pour gérer la mise à jour d’items existants : vérifier si un “id” a bien été défini par get_item_values() puis utilise la commande (1, ID, {valeurs})

Paramètres:items_values (list) – valeurs traduites pour les items
get_item_values(map_record, to_attr, options)[source]

Récupère la valeur brute des Mappeurs enfants depuis les items.

I peut être surchargé par exemple pour :

  • Changer des options
  • Utiliser un Binder pour savoir si un item existe déjà afin de le modifier au lieu de l’ajouter
Paramètres:
  • map_record (MapRecord) – enregistrement que nous sommes en train de convertir
  • to_attr (str) – champ destination (peut être utilisé pour inspecter la relation)
  • options – dictionnaire des options, hérité du mappeur principal
get_items(items, parent, to_attr, options)[source]

Renvoie la sortie formatée des valeurs des items pour un enregistrement principal

Paramètres:
  • items (list) – liste d’enregistrements d’items
  • parent – enregistrement parent
  • to_attr (str) – champ destination (peut être utilisé pour inspecter la relation)
  • options – dictionnaire des options, hérité du mappeur principal
Retourne:

valeurs de sortie formatées pour l’item

skip_item(map_record)[source]

Point d’accroche à implémenter dans les sous-classes lorsque certains enregistrements enfants doivent être sautés.

L’enregistrement parent est accessible dans map_record. S’il renvoie True, l’enregistrement enfant en cours est sauté.

Paramètres:map_record (MapRecord) – enregistrement que nous sommes en train de convertir
class connector.unit.mapper.MapOptions[source]

Bases : dict

Conteneur pour les options des mappeurs.

Des options peuvent être accédées grâce aux attributs de l’instance. Quand une option est accédée mais n’existe pas, ceci renvoie None.

class connector.unit.mapper.MapRecord(mapper, source, parent=None)[source]

Bases : object

Un enregistrement préparé à être converti en utilisans un Mapper.

Les instances de MapRecord sont préparées par Mapper.map_record().

Utilisation

mapper = SomeMapper(env)
map_record = mapper.map_record(record)
output_values = map_record.values()

Voir values() pour avoir plus d’informations sur les arguments disponibles.

parent

Enregistrement parent si l’enregistrement en cours est un item

source

Enregistrement source à convertir

update(*args, **kwargs)[source]

Force des valeurs à appliquer après une conversion.

Utilisation

mapper = SomeMapper(env)
map_record = mapper.map_record(record)
map_record.update(a=1)
output_values = map_record.values()
# output_values will at least contain {'a': 1}

Les valeurs affectées avec update() sont appliquées dans tous les cas, elles ont une priorité supérieure que les valeurs converties.

values(for_create=None, fields=None, **kwargs)[source]

Construit et renvoie les valeurs converties selon les options.

Utilisation

mapper = SomeMapper(env)
map_record = mapper.map_record(record)
output_values = map_record.values()
Création des enregistrements

En utilisant l’option for_create, seuls les mappings décorés avec @only_create seront mappés.

output_values = map_record.values(for_create=True)
Filtrer sur les champs

En utilisant l’argument fields, les mappings seront filtrés en utilisant soit la clé source dans les arguments direct, soit les arguments changed_by pour les méthodes de mapping.

output_values = map_record.values(fields=['name', 'street'])
Options spécifiques

Des clé et valeurs arbitraires peuvent être définies dans les arguments kwargs. Elles peuvent être ensuites utilisées dans les méthodes de mapping en utilisant self.options.

output_values = map_record.values(tax_include=True)
Paramètres:
  • for_create (boolean) – précise si seuls les mappings de création (@only_create) doivent être mappés.
  • fields (list) – filtre sur les champs
  • **kwargs – options spécifiques, elles peuvent être utilisées plus tard dans les méthodes de mapping
class connector.unit.mapper.Mapper(connector_env)[source]

Bases : connector.connector.ConnectorUnit

Un Mappeur convertit un enregistrement externe en enregistrement OpenERP et vice versa. La sortie d’un Traducteur est un dict.

3 types de mappings sont pris en charge :

Mappings directs

Exemples

direct = [('source', 'target')]

Ici le champs source sera copié vers le champ target.

Un modificateur peut être utilisé dans l’item source. Le modificateur sera appliqué au champ source avant d’être copié dans le champ destination. Il doit être une fonction de type closure pour respecter cet idiome

def a_function(field):
    ''' ``field`` is the name of the source field.

        Naming the arg: ``field`` is required for the conversion'''
    def modifier(self, record, to_attr):
        ''' self is the current Mapper,
            record is the current record to map,
            to_attr is the target field'''
        return record[field]
    return modifier

Et utilisé de cette façon

direct = [
        (a_function('source'), 'target'),
]

Un exemple plus concret de modificateur

def convert(field, conv_type):
    ''' Convert the source field to a defined ``conv_type``
    (ex. str) before returning it'''
    def modifier(self, record, to_attr):
        value = record[field]
        if not value:
            return None
        return conv_type(value)
    return modifier

Et utilisé de cette façon

direct = [
        (convert('myfield', float), 'target_field'),
]

D’autres exemples de modificateurs

Mappings par méthode

Un méthode de mapping permet d’exécuter un code arbitraire et de renvoyer un ou plusieurs champs

@mapping
def compute_state(self, record):
    # compute some state, using the ``record`` or not
    state = 'pending'
    return {'state': state}

Nous pouvons aussi préciser qu’une méthode de mapping doit être appliquée lorsqu’un objet est créé, mais jamais appliquée sur les mises à jour ultérieures

@only_create
@mapping
def default_warehouse(self, record):
    # get default warehouse
    warehouse_id = ...
    return {'warehouse_id': warehouse_id}
Sous-mappings

Lorsqu’un enregistrement contient des sous-items, comme les lignes d’une commande, nous pouvons convertir les enfants grâce à une autre Mappeur

children = [('items', 'line_ids', 'model.name')]

Il permet de créer des commandes et toutes ses lignes dans le même appel à openerp.models.BaseModel.create().

En utilisant des children pour les items d’un enregistrement, nous devons créer un Mapper pour le modèle des items, et de manière optionnelle un MapChild.

Utilisation d’un Mappeur

mapper = Mapper(env)
map_record = mapper.map_record(record)
values = map_record.values()
values = map_record.values(only_create=True)
values = map_record.values(fields=['name', 'street'])
children = []
direct = []
finalize(map_record, values)[source]

Appelé à la fin du mapping.

Peut être utilisé pour modifier les valeurs avant de les renvoyer, comme le on_change.

Paramètres:
  • map_record (MapRecord) – map_record source
  • values – valeurs mappées
Retourne:

valeurs mappées

Type retourné:

dict

map_methods

Émets toutes les méthodes décorées avec @mapping

map_record(record, parent=None)[source]

Récupère un MapRecord avec enregistrement, prêt à être converti avec le Mappeur en cours.

Paramètres:
  • record – enregistrement à transformer
  • parent – enregistrement parent optionnel, pour les items
options

Des options peuvent être accédées dans les méthodes de mapping avec self.options.

class connector.unit.mapper.MappingDefinition(changed_by, only_create)

Bases : tuple

changed_by

Alias pour le champ numéro 0

only_create

Alias pour le champs numéro 1

class connector.unit.mapper.MetaMapper(name, bases, attrs)[source]

Bases : connector.connector.MetaConnectorUnit

Metaclass pour Mappeur

construit un dict _map_methods des méthodes de mapping. Les clés de ce dict sont les noms de méthode. Les valeurs sont des namedtuple contenant :

connector.unit.mapper.backend_to_m2o(field, binding=None)[source]

Un modificateur destiné à être utilisé sur les mapping directs

Pour un champ d’un backend qui est un ID, recherche le binding correspondant dans OpenERP et renvoie son ID.

Quand la relation du champ n’est pas un binding (càd ne pointe pas vers quelque chose comme magento.*), le modèle de liaison doit être fourni avec l’argument nommé binding.

Exemples

direct = [(backend_to_m2o('country', binding='magento.res.country'),
           'country_id'),
          (backend_to_m2o('country'), 'magento_country_id')]
Paramètres:
  • field – nom du champ source dans l’enregistrement
  • binding – nom du modèle de liaison si la relation n’est pas une liaison
connector.unit.mapper.changed_by(*args)[source]

Décorateur pour les méthodes de mapping (mapping())

Lorsque des champs sont modifié dans OpenERP, nous ne devrions exporter que les champs modifiés. En utilisant ce décorateur, nous pouvons préciser quelles modifications de champs doivent déclencher quelle méthode de mapping.

Si changed_by est vide, le mapping est toujours actif.

Autant que possible, ce décorateur devrait être utilisé pour les exports. De cette façon lorsqu’on fait une modification sur une petite partie des champs d’un enregistrement, la taille de l’enregistrement en sortie sera limitée aux seuls champs devant être exportés.

Utilisation

@changed_by('input_field')
@mapping
def any(self, record):
    return {'output_field': record['input_field']}
Paramètres:*args – noms de champs qui déclenchent le mapping à la modification
connector.unit.mapper.convert(field, conv_type)[source]

Un modificateur destiné à être utilisé sur les mapping directs

Convertit une valeur de champ vers un type donné

Exemples

direct = [(convert('source', str), 'target')]
Paramètres:
  • field – nom du champ source dans l’enregistrement
  • binding – True si la relation est un enregistrement de binding
connector.unit.mapper.follow_m2o_relations(field)[source]

A modifier intended to be used on direct mappings.

“Follows” Many2one relations and return the final field value.

Exemples :

Assuming model is product.product:

direct = [
(follow_m2o_relations(“product_tmpl_id.categ_id.name”), “cat”)]
Paramètres:field – field « path », using dots for relations as usual in Odoo
connector.unit.mapper.m2o_to_backend(field, binding=None)[source]

Un modificateur destiné à être utilisé sur les mapping directs

Pour un many2one, récupère l’ID depuis le backend et le renvoie.

Quand la relation du champ n’est pas un binding (càd ne pointe pas vers quelque chose comme magento.*), le modèle de liaison doit être fourni avec l’argument nommé binding.

Exemples

direct = [(m2o_to_backend('country_id', binding='magento.res.country'),
           'country'),
          (m2o_to_backend('magento_country_id'), 'country')]
Paramètres:
  • field – nom du champ source dans l’enregistrement
  • binding – nom du modèle de liaison si la relation n’est pas une liaison
connector.unit.mapper.mapping(func)[source]

Déclare qu’une méthode est une méthode de mapping.

C’est ensuite utilisé par le Mapper pour convertir les enregistrements.

Utilisation

@mapping
def any(self, record):
    return {'output_field': record['input_field']}
connector.unit.mapper.none(field)[source]

Un modificateur destiné à être utilisé sur les mapping directs

Remplace les valeurs similaires à False par None. Ceci peut être utilisé dans un enchaînement de modificateurs quand .

Exemples

direct = [(none('source'), 'target'),
          (none(m2o_to_backend('rel_id'), 'rel_id')]
Paramètres:
  • field – nom du champ source dans l’enregistrement
  • binding – True si la relation est un enregistrement de binding
connector.unit.mapper.only_create(func)[source]

Décorateur pour les méthodes de mapping (mapping())

Un mapping décoré avec only_create indique qu’il doit être utilisé uniquement pour a création d’enregistrements.

Utilisation

@only_create
@mapping
def any(self, record):
    return {'output_field': record['input_field']}