Package Pyblio :: Module Adapter
[hide private]
[frames] | no frames]

Source Code for Module Pyblio.Adapter

  1  # This file is part of pybliographer 
  2  #  
  3  # Copyright (C) 1998-2006 Frederic GOBRY 
  4  # Email : gobry@pybliographer.org 
  5  #           
  6  # This program is free software; you can redistribute it and/or 
  7  # modify it under the terms of the GNU General Public License 
  8  # as published by the Free Software Foundation; either version 2  
  9  # of the License, or (at your option) any later version. 
 10  #    
 11  # This program is distributed in the hope that it will be useful, 
 12  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 13  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 14  # GNU General Public License for more details.  
 15  #  
 16  # You should have received a copy of the GNU General Public License 
 17  # along with this program; if not, write to the Free Software 
 18  # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. 
 19  #  
 20   
 21  """ 
 22  Adapt a database schema to another one. 
 23   
 24  Given a database in, say, PubMed format, it is possible to plug an 
 25  adapter on top of it so that it looks as if the database is in, say, 
 26  BibTeX format instead. 
 27  """ 
 28   
 29  from gettext import gettext as _ 
 30   
 31  from Pyblio.Store import Database 
 32  from Pyblio.Exceptions import AdaptError 
 33  from Pyblio import Registry 
 34   
 35   
36 -class Adapter(Database):
37 38 """ This class is a db built on top of another db, which behaves 39 as if it were of a different schema.""" 40 41 header = None 42
43 - def __init__(self, base):
44 self.base = base 45 return
46
47 - def save(self):
48 return self.base.save()
49
50 - def xmlread(self):
51 raise RuntimeError(_("Adapter databases cannot be read from file"))
52 53
54 -class ResultSetAdapter(object):
55 - def __init__(self, db, rs):
56 self.db = db 57 self.rs = rs
58
59 - def itervalues(self):
60 for k in self.rs.iterkeys(): 61 yield self.db[k]
62
63 - def iteritems(self):
64 for k in self.rs.iterkeys(): 65 yield k, self.db[k]
66
67 - def iterkeys(self):
68 return self.rs.iterkeys()
69
70 - def add(self, k):
71 self.rs.add(k)
72
73 - def __delitem__(self, k):
74 del self.rs[k]
75
76 -class ResultSetStoreAdapter(object):
77 - def __init__(self, db, adapted):
78 self.db = db 79 self.adapted = adapted
80
81 - def __getitem__ (self, k):
82 return ResultSetAdapter(self.adapted, self.db.rs[k])
83
84 - def __delitem__ (self, k):
85 del self.db.rs[k]
86
87 - def __iter__ (self):
88 return iter(self.db.rs)
89
90 - def new(self, rsid=None):
91 return ResultSetAdapter(self.adapted, self.db.rs.new())
92
93 - def update(self, result_set):
94 return self.db.rs.update(result_set)
95
96 -class OneToOneAdapter(Adapter):
97 """ This adapter assumes a one-to-one mapping between the source 98 and the target databases. The keys are not modified. """ 99
100 - def __init__(self, base):
101 Adapter.__init__(self, base) 102 self.rs = ResultSetStoreAdapter(base, self)
103
104 - def source2target(self, record):
105 """ Translates a record from the source db to the target db """ 106 raise NotImplemented('please override')
107
108 - def target2source(self, record):
109 """ Translates a record from the target db to the source db """ 110 raise NotImplemented('please override')
111
112 - def add(self, record):
113 return self.base.add(self.target2source(record))
114
115 - def __setitem__(self, key, record):
116 self.base[key] = self.target2source(record)
117
118 - def __getitem__(self, key):
119 return self.source2target(self.base[key])
120
121 - def has_key(self, key):
122 return self.base.has_key(key)
123
124 - def _entries(self):
125 e = self.base.entries 126 class Looper: 127 def itervalues(s): 128 for v in e.itervalues(): 129 yield self.source2target(v) 130 return
131 def iteritems(s): 132 for k, v in e.iteritems(): 133 yield k, self.source2target(v) 134 return
135 def iterkeys(s): 136 return e.iterkeys() 137 def __len__(s): 138 return len(e) 139 __iter__ = iterkeys 140 return Looper() 141 142 entries = property(_entries, None) 143
144 -def adapt_schema(db, target_schema):
145 """ Returns a database using the specified 'target_schema', and 146 that maps the content of 'db', thanks to one or more 147 L{Adapter}s. If no suitable adapter can be found, will raise an 148 AdaptError()""" 149 150 # for the moment, we only resolve direct hits. More clever 151 # resolutions will hopefully be implemented. 152 153 if db.schema.id == target_schema: 154 return db 155 156 # search for target_schema in the adapters for the current schema: 157 adapters = Registry.get(db.schema.id, 'adapters') 158 159 for adapter in adapters: 160 if adapter.target == target_schema: 161 return adapter()(db) 162 163 raise AdaptError(_("no adaptor for converting a %s into a %s") % ( 164 db.schema.id, target_schema))
165