~toolpart/openobject-server/toolpart

« back to all changes in this revision

Viewing changes to bin/addons/base/module/module.py.old

  • Committer: pinky
  • Date: 2006-12-07 13:41:40 UTC
  • Revision ID: pinky-3f10ee12cea3c4c75cef44ab04ad33ef47432907
New trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
##############################################################################
 
2
#
 
3
# Copyright (c) 2005 TINY SPRL. (http://tiny.be) All Rights Reserved.
 
4
#
 
5
# WARNING: This program as such is intended to be used by professional
 
6
# programmers who take the whole responsability of assessing all potential
 
7
# consequences resulting from its eventual inadequacies and bugs
 
8
# End users who are looking for a ready-to-use solution with commercial
 
9
# garantees and support are strongly adviced to contract a Free Software
 
10
# Service Company
 
11
#
 
12
# This program is Free Software; you can redistribute it and/or
 
13
# modify it under the terms of the GNU General Public License
 
14
# as published by the Free Software Foundation; either version 2
 
15
# of the License, or (at your option) any later version.
 
16
#
 
17
# This program is distributed in the hope that it will be useful,
 
18
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
19
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
20
# GNU General Public License for more details.
 
21
#
 
22
# You should have received a copy of the GNU General Public License
 
23
# along with this program; if not, write to the Free Software
 
24
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
25
#
 
26
##############################################################################
 
27
 
 
28
import tarfile
 
29
import re
 
30
import urllib2
 
31
import os
 
32
import shutil
 
33
from sets import Set
 
34
 
 
35
from osv import fields, osv 
 
36
import tools
 
37
 
 
38
class module(osv.osv):
 
39
        _name = "module.module"
 
40
        _description = "Module"
 
41
        
 
42
        def _costs_get(self, cr, uid, ids, prop=None, unknown_none=None, unknown_dict={}):
 
43
                dossiers = self.browse(cr, uid, ids)
 
44
                res = {}
 
45
                for d in dossiers:
 
46
                        costs = [l.amount_costs for l in d.lot_id]
 
47
                        cost_amount = reduce(lambda x, y: x+y, costs, 0.0)
 
48
                        res[d.id] = cost_amount 
 
49
                return res
 
50
                                                                                                                                                        
 
51
        _columns = {
 
52
                'name': fields.char("Name", size=128, readonly=True),
 
53
                'shortdesc': fields.char('Short description', size=256, readonly=True),
 
54
                'description': fields.text("Description", readonly=True),
 
55
                'author': fields.char("Author", size=128, readonly=True),
 
56
                'website': fields.char("Website", size=256, readonly=True),
 
57
#               'running_version': fields.function(_get_installed_version, method=True, string='Installed version'),
 
58
#               'installed_version': fields.function(_get_installed_version, method=True, string='Installed version'),
 
59
                'latest_version': fields.many2one('module.module.version', 'Latest version'),
 
60
                'versions': fields.one2many('module.module.version', 'module', 'Versions', readonly=True),
 
61
                'state': fields.selection([('uninstalled', 'Uninstalled'), ('preinstall','To install'),('installed','Installed'),('running','Running')], 'State'),
 
62
#               'active': fields.boolean('Active'),
 
63
        }
 
64
        
 
65
        # update the list of available packages
 
66
        def update(self, cr, uid, ids, *args):
 
67
                vobj = self.pool.get('module.module.version')
 
68
 
 
69
                # update installed_version
 
70
                
 
71
                # get the index page containing available packages from the server
 
72
                index_page = urllib2.urlopen('http://www.tinyerp.org/download/modules_test').read()
 
73
#               print index_page
 
74
                # parses it
 
75
                modules = re.findall('.*<a href="([a-zA-Z0-9.\-]+)_([a-zA-Z0-9.\-]+)\.tar\.gz">.*', index_page)
 
76
                # create module.module records and module.module.version as needed
 
77
                for name, version in modules:
 
78
                        print "name", name, "version", version
 
79
                        # open module package on the remote server and extract its __terp__.py
 
80
                        url = 'http://www.tinyerp.org/download/modules_test/' + name + '_' + version + ".tar.gz"
 
81
                        tar = tarfile.open(mode="r|gz", fileobj=urllib2.urlopen(url))
 
82
                        info = {}
 
83
                        # we need to go through the whole tar file, because we use a stream and we
 
84
                        # are not allowed to search backward in the stream, so we can't extract one
 
85
                        # particular file directly
 
86
                        for tarinfo in tar:
 
87
                                if tarinfo.name.endswith('__terp__.py'):
 
88
                                        info = eval(tar.extractfile(tarinfo).read())
 
89
                                        break
 
90
                        tar.close()
 
91
                        print info
 
92
                        ids = self.search(cr, uid, [('name','=',name)])
 
93
                        print ids
 
94
                        if not ids:
 
95
                                id = self.create(cr, uid, {
 
96
                                        'name': name, 
 
97
                                        'shortdesc': info.get('name', False), 
 
98
                                        'description': info.get('description', False),
 
99
                                        'author': info.get('author', False),
 
100
                                        'website': info.get('website', False),
 
101
                                        'state': 'uninstalled',
 
102
                                })
 
103
                                print "module_id", id
 
104
                        else:
 
105
                                assert len(ids)==1, "There shouldn't be two modules with the same name"
 
106
                                id = ids[0]
 
107
                                
 
108
                        version_ids = vobj.search(cr, uid, [('module','=',id),('name','=',version)])
 
109
                        print version_ids
 
110
                        if not version_ids:
 
111
                                version_id = vobj.create(cr, uid, {
 
112
                                        'name': version, 
 
113
                                        'module': id,
 
114
                                        'state': 'uninstalled',
 
115
                                })
 
116
                                print "version_id", version_id
 
117
                                # update latest_version
 
118
                                #TODO: compute latest version
 
119
                                self.write(cr, uid, [id], {'latest_version': version_id})
 
120
#                       else:
 
121
#                               assert len(version_ids)==1, "There shouldn't be two versions with the same name"
 
122
#                               version_id = version_ids[0]
 
123
                        
 
124
                return True
 
125
 
 
126
        def install(self, cr, uid, ids, *args):
 
127
                objs = self.browse(cr, uid, ids)
 
128
                vobj = self.pool.get('module.module.version')
 
129
                
 
130
                # get the id of latest version for each module
 
131
                version_ids = Set([o.latest_version.id for o in objs])
 
132
#               for o in objs:
 
133
#                       version_ids.add()
 
134
#               version_ids = reduce(lambda dic, o: dic.update({o.latest_version.id:True}), objs, {})
 
135
                print "version_ids", version_ids
 
136
                
 
137
                # add the list of dependencies
 
138
                dependencies_ids = vobj.get_dependencies(cr, uid, list(version_ids))
 
139
                print "depends", dependencies_ids
 
140
                version_ids.update(dependencies_ids)
 
141
#               version_ids = reduce(lambda dic, dep: dic.update({dep:True}), dependencies_ids, version_ids)
 
142
                print "version_ids2", version_ids
 
143
                        
 
144
                # remove existing version of modules
 
145
                self.remove(cr, uid, ids)
 
146
                
 
147
                # install all selected modules and their dependencies
 
148
                vobj.install(cr, uid, list(version_ids))
 
149
                return True
 
150
        
 
151
 
 
152
        # remove existing version of modules if they exist
 
153
        def remove(self, cr, uid, ids, *args):
 
154
                objs = self.browse(cr, uid, ids)
 
155
                adp = tools.config['addons_path']
 
156
                addons = os.listdir(adp)
 
157
                for o in objs:
 
158
                        if o.name in addons:
 
159
                                shutil.rmtree(os.path.join(adp, o.name))
 
160
                return True
 
161
module()
 
162
 
 
163
class module_version(osv.osv):
 
164
        _name = "module.module.version"
 
165
        _description = "Module Version"
 
166
        _columns = {
 
167
                'name': fields.char('Name', size=64),
 
168
                'module': fields.many2one('module.module', "Module"),
 
169
                'dependencies': fields.one2many('module.module.dependency', 'version', 'Dependencies'),
 
170
                'state': fields.selection([('uninstalled','Uninstalled'), ('preinstall','To install'), ('installed','Installed'), ('running','Running')], 'State'),
 
171
        }
 
172
 
 
173
        def install(self, cr, uid, ids, *args):
 
174
                print "install versions", ids
 
175
                objs = self.browse(cr, uid, ids)
 
176
 
 
177
                for o in objs:
 
178
                        # download and unpack to destination folder
 
179
                        url = 'http://www.tinyerp.org/download/modules_test/' + o.module.name + '_' + o.name + ".tar.gz"
 
180
                        tar = tarfile.open(mode="r|gz", fileobj=urllib2.urlopen(url))
 
181
                        for tarinfo in tar:
 
182
                                tar.extract(tarinfo, tools.config['addons_path'])
 
183
                return True
 
184
        
 
185
        def get_dependencies(self, cr, uid, ids, *args):
 
186
                dobj = self.pool.get('module.module.dependency')
 
187
                print "get_depends", ids
 
188
                # for each dependency, get dependencies
 
189
                objs = self.browse(cr, uid, ids)
 
190
                depends = []
 
191
                for o in objs:
 
192
                        print "name", o.name
 
193
                        o_depends = dobj.resolve(cr, uid, [d.id for d in o.dependencies])
 
194
                        print "depends", o_depends
 
195
                        depends.extend(o_depends)
 
196
                        
 
197
#                       depends.extend([d.id for d in o.dependencies])
 
198
                print "total depends", depends
 
199
                # merge the list 
 
200
                # return the list of ids
 
201
                return depends
 
202
module_version()
 
203
 
 
204
# a module dependency record represents one dependency of a particular version of a module
 
205
# it can depend on a range of version of one module
 
206
class module_dependency(osv.osv):
 
207
        _name = "module.module.dependency"
 
208
        _description = "Module dependency"
 
209
        _columns = {
 
210
                'dependency_for': fields.many2one('module.module.version', 'Version'),
 
211
                'module': fields.many2one('module.module', 'Module'),
 
212
                'version_pattern': fields.char('Version pattern', size=128),
 
213
        }
 
214
        
 
215
        # returns the ids of module version records which match all dependencies
 
216
        # [version_id, ...]
 
217
        def resolve(self, cr, uid, ids):
 
218
                vobj = self.pool.get('module.module.version')
 
219
                objs = self.browse(cr, uid, ids)
 
220
                res = {}
 
221
                for o in objs:
 
222
                        pattern = o.version_pattern and eval(o.version_pattern) or []
 
223
                        print "pattern", pattern
 
224
                        res[o.id] = vobj.search(cr, uid, [('module','=',o.module.id)]+pattern)
 
225
                #TODO: add smart dependencies resolver here
 
226
                # it should compute the best version for each module
 
227
                return [r[0] for r in res.itervalues()]
 
228
module_dependency()