delete unused and untested modules (closes #2402)

It's spring^Wsummer cleaning time.

authorRémi Cardona <remi.cardona@logilab.fr>
changeset7d33521d00ab
branchdefault
phasepublic
hiddenno
parent revision#debb3a42631a [testlib] remove support for deprecated module level fixture names
child revision#efa750aa7e15 Update changelog
files modified by this revision
debian/control
logilab/common/cli.py
logilab/common/contexts.py
logilab/common/corbautils.py
logilab/common/dbf.py
logilab/common/pyro_ext.py
logilab/common/xmlrpcutils.py
# HG changeset patch
# User Rémi Cardona <remi.cardona@logilab.fr>
# Date 1435313254 -7200
# Fri Jun 26 12:07:34 2015 +0200
# Node ID 7d33521d00ab82cf9bff3e9b3f1c9066c0ed4500
# Parent debb3a42631a069504b09845450799c8b6dc282c
delete unused and untested modules (closes #2402)

It's spring^Wsummer cleaning time.

diff --git a/debian/control b/debian/control
@@ -37,11 +37,10 @@
1   ${python:Depends},
2   ${misc:Depends},
3  Recommends:
4   python-egenix-mxdatetime
5  Suggests:
6 - pyro,
7   python-unittest2,
8   python-kerberos,
9  Conflicts:
10   python-constraint (<< 0.4.0-4),
11   python-logilab-astng (<< 0.19.1-1),
@@ -57,11 +56,10 @@
12   designed to ease:
13   .
14    * handling command line options and configuration files
15    * writing interactive command line tools
16    * manipulation files and character strings
17 -  * interfacing to OmniORB
18    * running unit tests
19    * manipulating tree structures
20    * generating text and HTML reports
21    * logging
22    * parsing XML processing instructions
@@ -83,11 +81,10 @@
23   designed to ease:
24   .
25    * handling command line options and configuration files
26    * writing interactive command line tools
27    * manipulation files and character strings
28 -  * interfacing to OmniORB
29    * running unit tests
30    * manipulating tree structures
31    * generating text and HTML reports
32    * logging
33   .
diff --git a/logilab/common/cli.py b/logilab/common/cli.py
@@ -1,211 +0,0 @@
34 -# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
35 -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
36 -#
37 -# This file is part of logilab-common.
38 -#
39 -# logilab-common is free software: you can redistribute it and/or modify it under
40 -# the terms of the GNU Lesser General Public License as published by the Free
41 -# Software Foundation, either version 2.1 of the License, or (at your option) any
42 -# later version.
43 -#
44 -# logilab-common is distributed in the hope that it will be useful, but WITHOUT
45 -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
46 -# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
47 -# details.
48 -#
49 -# You should have received a copy of the GNU Lesser General Public License along
50 -# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
51 -"""Command line interface helper classes.
52 -
53 -It provides some default commands, a help system, a default readline
54 -configuration with completion and persistent history.
55 -
56 -Example::
57 -
58 -    class BookShell(CLIHelper):
59 -
60 -        def __init__(self):
61 -            # quit and help are builtins
62 -            # CMD_MAP keys are commands, values are topics
63 -            self.CMD_MAP['pionce'] = _("Sommeil")
64 -            self.CMD_MAP['ronfle'] = _("Sommeil")
65 -            CLIHelper.__init__(self)
66 -
67 -        help_do_pionce = ("pionce", "pionce duree", _("met ton corps en veille"))
68 -        def do_pionce(self):
69 -            print('nap is good')
70 -
71 -        help_do_ronfle = ("ronfle", "ronfle volume", _("met les autres en veille"))
72 -        def do_ronfle(self):
73 -            print('fuuuuuuuuuuuu rhhhhhrhrhrrh')
74 -
75 -    cl = BookShell()
76 -"""
77 -
78 -from __future__ import print_function
79 -
80 -__docformat__ = "restructuredtext en"
81 -
82 -from six.moves import builtins, input
83 -
84 -if not hasattr(builtins, '_'):
85 -    builtins._ = str
86 -
87 -
88 -def init_readline(complete_method, histfile=None):
89 -    """Init the readline library if available."""
90 -    try:
91 -        import readline
92 -        readline.parse_and_bind("tab: complete")
93 -        readline.set_completer(complete_method)
94 -        string = readline.get_completer_delims().replace(':', '')
95 -        readline.set_completer_delims(string)
96 -        if histfile is not None:
97 -            try:
98 -                readline.read_history_file(histfile)
99 -            except IOError:
100 -                pass
101 -            import atexit
102 -            atexit.register(readline.write_history_file, histfile)
103 -    except:
104 -        print('readline is not available :-(')
105 -
106 -
107 -class Completer :
108 -    """Readline completer."""
109 -
110 -    def __init__(self, commands):
111 -        self.list = commands
112 -
113 -    def complete(self, text, state):
114 -        """Hook called by readline when <tab> is pressed."""
115 -        n = len(text)
116 -        matches = []
117 -        for cmd in self.list :
118 -            if cmd[:n] == text :
119 -                matches.append(cmd)
120 -        try:
121 -            return matches[state]
122 -        except IndexError:
123 -            return None
124 -
125 -
126 -class CLIHelper:
127 -    """An abstract command line interface client which recognize commands
128 -    and provide an help system.
129 -    """
130 -
131 -    CMD_MAP = {'help': _("Others"),
132 -               'quit': _("Others"),
133 -               }
134 -    CMD_PREFIX = ''
135 -
136 -    def __init__(self, histfile=None) :
137 -        self._topics = {}
138 -        self.commands = None
139 -        self._completer = Completer(self._register_commands())
140 -        init_readline(self._completer.complete, histfile)
141 -
142 -    def run(self):
143 -        """loop on user input, exit on EOF"""
144 -        while True:
145 -            try:
146 -                line = input('>>> ')
147 -            except EOFError:
148 -                print
149 -                break
150 -            s_line = line.strip()
151 -            if not s_line:
152 -                continue
153 -            args = s_line.split()
154 -            if args[0] in self.commands:
155 -                try:
156 -                    cmd = 'do_%s' % self.commands[args[0]]
157 -                    getattr(self, cmd)(*args[1:])
158 -                except EOFError:
159 -                    break
160 -                except:
161 -                    import traceback
162 -                    traceback.print_exc()
163 -            else:
164 -                try:
165 -                    self.handle_line(s_line)
166 -                except:
167 -                    import traceback
168 -                    traceback.print_exc()
169 -
170 -    def handle_line(self, stripped_line):
171 -        """Method to overload in the concrete class (should handle
172 -        lines which are not commands).
173 -        """
174 -        raise NotImplementedError()
175 -
176 -
177 -    # private methods #########################################################
178 -
179 -    def _register_commands(self):
180 -        """ register available commands method and return the list of
181 -        commands name
182 -        """
183 -        self.commands = {}
184 -        self._command_help = {}
185 -        commands = [attr[3:] for attr in dir(self) if attr[:3] == 'do_']
186 -        for command in commands:
187 -            topic = self.CMD_MAP[command]
188 -            help_method = getattr(self, 'help_do_%s' % command)
189 -            self._topics.setdefault(topic, []).append(help_method)
190 -            self.commands[self.CMD_PREFIX + command] = command
191 -            self._command_help[command] = help_method
192 -        return self.commands.keys()
193 -
194 -    def _print_help(self, cmd, syntax, explanation):
195 -        print(_('Command %s') % cmd)
196 -        print(_('Syntax: %s') % syntax)
197 -        print('\t', explanation)
198 -        print()
199 -
200 -
201 -    # predefined commands #####################################################
202 -
203 -    def do_help(self, command=None) :
204 -        """base input of the help system"""
205 -        if command in self._command_help:
206 -            self._print_help(*self._command_help[command])
207 -        elif command is None or command not in self._topics:
208 -            print(_("Use help <topic> or help <command>."))
209 -            print(_("Available topics are:"))
210 -            topics = sorted(self._topics.keys())
211 -            for topic in topics:
212 -                print('\t', topic)
213 -            print()
214 -            print(_("Available commands are:"))
215 -            commands = self.commands.keys()
216 -            commands.sort()
217 -            for command in commands:
218 -                print('\t', command[len(self.CMD_PREFIX):])
219 -
220 -        else:
221 -            print(_('Available commands about %s:') % command)
222 -            print
223 -            for command_help_method in self._topics[command]:
224 -                try:
225 -                    if callable(command_help_method):
226 -                        self._print_help(*command_help_method())
227 -                    else:
228 -                        self._print_help(*command_help_method)
229 -                except:
230 -                    import traceback
231 -                    traceback.print_exc()
232 -                    print('ERROR in help method %s'% (
233 -                        command_help_method.__name__))
234 -
235 -    help_do_help = ("help", "help [topic|command]",
236 -                    _("print help message for the given topic/command or \
237 -available topics when no argument"))
238 -
239 -    def do_quit(self):
240 -        """quit the CLI"""
241 -        raise EOFError()
242 -
243 -    def help_do_quit(self):
244 -        return ("quit", "quit", _("quit the application"))
diff --git a/logilab/common/contexts.py b/logilab/common/contexts.py
@@ -1,5 +0,0 @@
245 -from warnings import warn
246 -warn('logilab.common.contexts module is deprecated, use logilab.common.shellutils instead',
247 -     DeprecationWarning, stacklevel=1)
248 -
249 -from logilab.common.shellutils import tempfile, pushd
diff --git a/logilab/common/corbautils.py b/logilab/common/corbautils.py
@@ -1,117 +0,0 @@
250 -# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
251 -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
252 -#
253 -# This file is part of logilab-common.
254 -#
255 -# logilab-common is free software: you can redistribute it and/or modify it under
256 -# the terms of the GNU Lesser General Public License as published by the Free
257 -# Software Foundation, either version 2.1 of the License, or (at your option) any
258 -# later version.
259 -#
260 -# logilab-common is distributed in the hope that it will be useful, but WITHOUT
261 -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
262 -# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
263 -# details.
264 -#
265 -# You should have received a copy of the GNU Lesser General Public License along
266 -# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
267 -"""A set of utility function to ease the use of OmniORBpy.
268 -
269 -
270 -
271 -
272 -"""
273 -__docformat__ = "restructuredtext en"
274 -
275 -from omniORB import CORBA, PortableServer
276 -import CosNaming
277 -
278 -orb = None
279 -
280 -def get_orb():
281 -    """
282 -    returns a reference to the ORB.
283 -    The first call to the method initialized the ORB
284 -    This method is mainly used internally in the module.
285 -    """
286 -
287 -    global orb
288 -    if orb is None:
289 -        import sys
290 -        orb = CORBA.ORB_init(sys.argv, CORBA.ORB_ID)
291 -    return orb
292 -
293 -def get_root_context():
294 -    """
295 -    returns a reference to the NameService object.
296 -    This method is mainly used internally in the module.
297 -    """
298 -
299 -    orb = get_orb()
300 -    nss = orb.resolve_initial_references("NameService")
301 -    rootContext = nss._narrow(CosNaming.NamingContext)
302 -    assert rootContext is not None, "Failed to narrow root naming context"
303 -    return rootContext
304 -
305 -def register_object_name(object, namepath):
306 -    """
307 -    Registers a object in the NamingService.
308 -    The name path is a list of 2-uples (id,kind) giving the path.
309 -
310 -    For instance if the path of an object is [('foo',''),('bar','')],
311 -    it is possible to get a reference to the object using the URL
312 -    'corbaname::hostname#foo/bar'.
313 -    [('logilab','rootmodule'),('chatbot','application'),('chatter','server')]
314 -    is mapped to
315 -    'corbaname::hostname#logilab.rootmodule/chatbot.application/chatter.server'
316 -
317 -    The get_object_reference() function can be used to resolve such a URL.
318 -    """
319 -    context = get_root_context()
320 -    for id, kind in namepath[:-1]:
321 -        name = [CosNaming.NameComponent(id, kind)]
322 -        try:
323 -            context = context.bind_new_context(name)
324 -        except CosNaming.NamingContext.AlreadyBound as ex:
325 -            context = context.resolve(name)._narrow(CosNaming.NamingContext)
326 -            assert context is not None, \
327 -                   'test context exists but is not a NamingContext'
328 -
329 -    id, kind = namepath[-1]
330 -    name = [CosNaming.NameComponent(id, kind)]
331 -    try:
332 -        context.bind(name, object._this())
333 -    except CosNaming.NamingContext.AlreadyBound as ex:
334 -        context.rebind(name, object._this())
335 -
336 -def activate_POA():
337 -    """
338 -    This methods activates the Portable Object Adapter.
339 -    You need to call it to enable the reception of messages in your code,
340 -    on both the client and the server.
341 -    """
342 -    orb = get_orb()
343 -    poa = orb.resolve_initial_references('RootPOA')
344 -    poaManager = poa._get_the_POAManager()
345 -    poaManager.activate()
346 -
347 -def run_orb():
348 -    """
349 -    Enters the ORB mainloop on the server.
350 -    You should not call this method on the client.
351 -    """
352 -    get_orb().run()
353 -
354 -def get_object_reference(url):
355 -    """
356 -    Resolves a corbaname URL to an object proxy.
357 -    See register_object_name() for examples URLs
358 -    """
359 -    return get_orb().string_to_object(url)
360 -
361 -def get_object_string(host, namepath):
362 -    """given an host name and a name path as described in register_object_name,
363 -    return a corba string identifier
364 -    """
365 -    strname = '/'.join(['.'.join(path_elt) for path_elt in namepath])
366 -    return 'corbaname::%s#%s' % (host, strname)
diff --git a/logilab/common/dbf.py b/logilab/common/dbf.py
@@ -1,231 +0,0 @@
367 -# -*- coding: utf-8 -*-
368 -# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
369 -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
370 -#
371 -# This file is part of logilab-common.
372 -#
373 -# logilab-common is free software: you can redistribute it and/or modify it under
374 -# the terms of the GNU Lesser General Public License as published by the Free
375 -# Software Foundation, either version 2.1 of the License, or (at your option) any
376 -# later version.
377 -#
378 -# logilab-common is distributed in the hope that it will be useful, but WITHOUT
379 -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
380 -# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
381 -# details.
382 -#
383 -# You should have received a copy of the GNU Lesser General Public License along
384 -# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
385 -"""This is a DBF reader which reads Visual Fox Pro DBF format with Memo field
386 -
387 -Usage:
388 -
389 ->>> rec = readDbf('test.dbf')
390 ->>> for line in rec:
391 ->>>     print line['name']
392 -
393 -
394 -:date: 13/07/2007
395 -
396 -http://www.physics.ox.ac.uk/users/santoso/Software.Repository.html
397 -page says code is "available as is without any warranty or support".
398 -"""
399 -from __future__ import print_function
400 -
401 -import struct
402 -import os, os.path
403 -import sys
404 -import csv
405 -import tempfile
406 -
407 -from six.moves import range
408 -
409 -class Dbase:
410 -    def __init__(self):
411 -        self.fdb = None
412 -        self.fmemo = None
413 -        self.db_data = None
414 -        self.memo_data = None
415 -        self.fields = None
416 -        self.num_records = 0
417 -        self.header = None
418 -        self.memo_file = ''
419 -        self.memo_header = None
420 -        self.memo_block_size = 0
421 -        self.memo_header_len = 0
422 -
423 -    def _drop_after_NULL(self, txt):
424 -        for i in range(0, len(txt)):
425 -            if ord(struct.unpack('c', txt[i])[0])==0:
426 -                return txt[:i]
427 -        return txt
428 -
429 -    def _reverse_endian(self, num):
430 -        if not len(num):
431 -            return 0
432 -        val = struct.unpack('<L', num)
433 -        val = struct.pack('>L', val[0])
434 -        val = struct.unpack('>L', val)
435 -        return val[0]
436 -
437 -    def _assign_ids(self, lst, ids):
438 -        result = {}
439 -        idx = 0
440 -        for item in lst:
441 -            id = ids[idx]
442 -            result[id] = item
443 -            idx += 1
444 -        return result
445 -
446 -    def open(self, db_name):
447 -        filesize = os.path.getsize(db_name)
448 -        if filesize <= 68:
449 -            raise IOError('The file is not large enough to be a dbf file')
450 -
451 -        self.fdb = open(db_name, 'rb')
452 -
453 -        self.memo_file = ''
454 -        if os.path.isfile(db_name[0:-1] + 't'):
455 -            self.memo_file = db_name[0:-1] + 't'
456 -        elif os.path.isfile(db_name[0:-3] + 'fpt'):
457 -            self.memo_file = db_name[0:-3] + 'fpt'
458 -
459 -        if self.memo_file:
460 -            #Read memo file
461 -            self.fmemo = open(self.memo_file, 'rb')
462 -            self.memo_data = self.fmemo.read()
463 -            self.memo_header = self._assign_ids(struct.unpack('>6x1H', self.memo_data[:8]), ['Block size'])
464 -            block_size = self.memo_header['Block size']
465 -            if not block_size:
466 -                block_size = 512
467 -            self.memo_block_size = block_size
468 -            self.memo_header_len = block_size
469 -            memo_size = os.path.getsize(self.memo_file)
470 -
471 -        #Start reading data file
472 -        data = self.fdb.read(32)
473 -        self.header = self._assign_ids(struct.unpack('<B 3B L 2H 20x', data), ['id', 'Year', 'Month', 'Day', '# of Records', 'Header Size', 'Record Size'])
474 -        self.header['id'] = hex(self.header['id'])
475 -
476 -        self.num_records = self.header['# of Records']
477 -        data = self.fdb.read(self.header['Header Size']-34)
478 -        self.fields = {}
479 -        x = 0
480 -        header_pattern = '<11s c 4x B B 14x'
481 -        ids = ['Field Name', 'Field Type', 'Field Length', 'Field Precision']
482 -        pattern_len = 32
483 -        for offset in range(0, len(data), 32):
484 -            if ord(data[offset])==0x0d:
485 -                break
486 -            x += 1
487 -            data_subset = data[offset: offset+pattern_len]
488 -            if len(data_subset) < pattern_len:
489 -                data_subset += ' '*(pattern_len-len(data_subset))
490 -            self.fields[x] = self._assign_ids(struct.unpack(header_pattern, data_subset), ids)
491 -            self.fields[x]['Field Name'] = self._drop_after_NULL(self.fields[x]['Field Name'])
492 -
493 -        self.fdb.read(3)
494 -        if self.header['# of Records']:
495 -            data_size = (self.header['# of Records'] * self.header['Record Size']) - 1
496 -            self.db_data = self.fdb.read(data_size)
497 -        else:
498 -            self.db_data = ''
499 -        self.row_format = '<'
500 -        self.row_ids = []
501 -        self.row_len = 0
502 -        for key in self.fields:
503 -            field = self.fields[key]
504 -            self.row_format += '%ds ' % (field['Field Length'])
505 -            self.row_ids.append(field['Field Name'])
506 -            self.row_len += field['Field Length']
507 -
508 -    def close(self):
509 -        if self.fdb:
510 -            self.fdb.close()
511 -        if self.fmemo:
512 -            self.fmemo.close()
513 -
514 -    def get_numrecords(self):
515 -        return self.num_records
516 -
517 -    def get_record_with_names(self, rec_no):
518 -        """
519 -        This function accept record number from 0 to N-1
520 -        """
521 -        if rec_no < 0 or rec_no > self.num_records:
522 -            raise Exception('Unable to extract data outside the range')
523 -
524 -        offset = self.header['Record Size'] * rec_no
525 -        data = self.db_data[offset:offset+self.row_len]
526 -        record = self._assign_ids(struct.unpack(self.row_format, data), self.row_ids)
527 -
528 -        if self.memo_file:
529 -            for key in self.fields:
530 -                field = self.fields[key]
531 -                f_type = field['Field Type']
532 -                f_name = field['Field Name']
533 -                c_data = record[f_name]
534 -
535 -                if f_type=='M' or f_type=='G' or f_type=='B' or f_type=='P':
536 -                    c_data = self._reverse_endian(c_data)
537 -                    if c_data:
538 -                        record[f_name] = self.read_memo(c_data-1).strip()
539 -                else:
540 -                    record[f_name] = c_data.strip()
541 -        return record
542 -
543 -    def read_memo_record(self, num, in_length):
544 -        """
545 -        Read the record of given number. The second parameter is the length of
546 -        the record to read. It can be undefined, meaning read the whole record,
547 -        and it can be negative, meaning at most the length
548 -        """
549 -        if in_length < 0:
550 -            in_length = -self.memo_block_size
551 -
552 -        offset = self.memo_header_len + num * self.memo_block_size
553 -        self.fmemo.seek(offset)
554 -        if in_length<0:
555 -            in_length = -in_length
556 -        if in_length==0:
557 -            return ''
558 -        return self.fmemo.read(in_length)
559 -
560 -    def read_memo(self, num):
561 -        result = ''
562 -        buffer = self.read_memo_record(num, -1)
563 -        if len(buffer)<=0:
564 -            return ''
565 -        length = struct.unpack('>L', buffer[4:4+4])[0] + 8
566 -
567 -        block_size = self.memo_block_size
568 -        if length < block_size:
569 -            return buffer[8:length]
570 -        rest_length = length - block_size
571 -        rest_data = self.read_memo_record(num+1, rest_length)
572 -        if len(rest_data)<=0:
573 -            return ''
574 -        return buffer[8:] + rest_data
575 -
576 -def readDbf(filename):
577 -    """
578 -    Read the DBF file specified by the filename and
579 -    return the records as a list of dictionary.
580 -
581 -    :param: filename File name of the DBF
582 -    :return: List of rows
583 -    """
584 -    db = Dbase()
585 -    db.open(filename)
586 -    num = db.get_numrecords()
587 -    rec = []
588 -    for i in range(0, num):
589 -        record = db.get_record_with_names(i)
590 -        rec.append(record)
591 -    db.close()
592 -    return  rec
593 -
594 -if __name__=='__main__':
595 -    rec = readDbf('dbf/sptable.dbf')
596 -    for line in rec:
597 -        print('%s %s' % (line['GENUS'].strip(), line['SPECIES'].strip()))
diff --git a/logilab/common/pyro_ext.py b/logilab/common/pyro_ext.py
@@ -1,180 +0,0 @@
598 -# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
599 -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
600 -#
601 -# This file is part of logilab-common.
602 -#
603 -# logilab-common is free software: you can redistribute it and/or modify it under
604 -# the terms of the GNU Lesser General Public License as published by the Free
605 -# Software Foundation, either version 2.1 of the License, or (at your option) any
606 -# later version.
607 -#
608 -# logilab-common is distributed in the hope that it will be useful, but WITHOUT
609 -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
610 -# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
611 -# details.
612 -#
613 -# You should have received a copy of the GNU Lesser General Public License along
614 -# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
615 -"""Python Remote Object utilities
616 -
617 -Main functions available:
618 -
619 -* `register_object` to expose arbitrary object through pyro using delegation
620 -  approach and register it in the nameserver.
621 -* `ns_unregister` unregister an object identifier from the nameserver.
622 -* `ns_get_proxy` get a pyro proxy from a nameserver object identifier.
623 -"""
624 -
625 -__docformat__ = "restructuredtext en"
626 -
627 -import logging
628 -import tempfile
629 -
630 -from Pyro import core, naming, errors, util, config
631 -
632 -_LOGGER = logging.getLogger('pyro')
633 -_MARKER = object()
634 -
635 -config.PYRO_STORAGE = tempfile.gettempdir()
636 -
637 -def ns_group_and_id(idstr, defaultnsgroup=_MARKER):
638 -    try:
639 -        nsgroup, nsid = idstr.rsplit('.', 1)
640 -    except ValueError:
641 -        if defaultnsgroup is _MARKER:
642 -            nsgroup = config.PYRO_NS_DEFAULTGROUP
643 -        else:
644 -            nsgroup = defaultnsgroup
645 -        nsid = idstr
646 -    if nsgroup is not None and not nsgroup.startswith(':'):
647 -        nsgroup = ':' + nsgroup
648 -    return nsgroup, nsid
649 -
650 -def host_and_port(hoststr):
651 -    if not hoststr:
652 -        return None, None
653 -    try:
654 -        hoststr, port = hoststr.split(':')
655 -    except ValueError:
656 -        port = None
657 -    else:
658 -        port = int(port)
659 -    return hoststr, port
660 -
661 -_DAEMONS = {}
662 -_PYRO_OBJS = {}
663 -def _get_daemon(daemonhost, start=True):
664 -    if not daemonhost in _DAEMONS:
665 -        if not start:
666 -            raise Exception('no daemon for %s' % daemonhost)
667 -        if not _DAEMONS:
668 -            core.initServer(banner=0)
669 -        host, port = host_and_port(daemonhost)
670 -        daemon = core.Daemon(host=host, port=port)
671 -        _DAEMONS[daemonhost] = daemon
672 -    return _DAEMONS[daemonhost]
673 -
674 -
675 -def locate_ns(nshost):
676 -    """locate and return the pyro name server to the daemon"""
677 -    core.initClient(banner=False)
678 -    return naming.NameServerLocator().getNS(*host_and_port(nshost))
679 -
680 -
681 -def register_object(object, nsid, defaultnsgroup=_MARKER,
682 -                    daemonhost=None, nshost=None, use_pyrons=True):
683 -    """expose the object as a pyro object and register it in the name-server
684 -
685 -    if use_pyrons is False, then the object is exposed, but no
686 -    attempt to register it to a pyro nameserver is made.
687 -
688 -    return the pyro daemon object
689 -    """
690 -    nsgroup, nsid = ns_group_and_id(nsid, defaultnsgroup)
691 -    daemon = _get_daemon(daemonhost)
692 -    if use_pyrons:
693 -        nsd = locate_ns(nshost)
694 -        # make sure our namespace group exists
695 -        try:
696 -            nsd.createGroup(nsgroup)
697 -        except errors.NamingError:
698 -            pass
699 -        daemon.useNameServer(nsd)
700 -    # use Delegation approach
701 -    impl = core.ObjBase()
702 -    impl.delegateTo(object)
703 -    qnsid = '%s.%s' % (nsgroup, nsid)
704 -    uri = daemon.connect(impl, qnsid)
705 -    _PYRO_OBJS[qnsid] = str(uri)
706 -    _LOGGER.info('registered %s a pyro object using group %s and id %s',
707 -                 object, nsgroup, nsid)
708 -    return daemon
709 -
710 -def get_object_uri(qnsid):
711 -    return _PYRO_OBJS[qnsid]
712 -
713 -def ns_unregister(nsid, defaultnsgroup=_MARKER, nshost=None):
714 -    """unregister the object with the given nsid from the pyro name server"""
715 -    nsgroup, nsid = ns_group_and_id(nsid, defaultnsgroup)
716 -    try:
717 -        nsd = locate_ns(nshost)
718 -    except errors.PyroError as ex:
719 -        # name server not responding
720 -        _LOGGER.error('can\'t locate pyro name server: %s', ex)
721 -    else:
722 -        try:
723 -            nsd.unregister('%s.%s' % (nsgroup, nsid))
724 -            _LOGGER.info('%s unregistered from pyro name server', nsid)
725 -        except errors.NamingError:
726 -            _LOGGER.warning('%s not registered in pyro name server', nsid)
727 -
728 -
729 -def ns_reregister(nsid, defaultnsgroup=_MARKER, nshost=None):
730 -    """reregister a pyro object into the name server. You only have to specify
731 -    the name-server id of the object (though you MUST have gone through
732 -    `register_object` for the given object previously).
733 -
734 -    This is especially useful for long running server while the name server may
735 -    have been restarted, and its records lost.
736 -    """
737 -    nsgroup, nsid = ns_group_and_id(nsid, defaultnsgroup)
738 -    qnsid = '%s.%s' % (nsgroup, nsid)
739 -    nsd = locate_ns(nshost)
740 -    try:
741 -        nsd.unregister(qnsid)
742 -    except errors.NamingError:
743 -        # make sure our namespace group exists
744 -        try:
745 -            nsd.createGroup(nsgroup)
746 -        except errors.NamingError:
747 -            pass
748 -    nsd.register(qnsid, _PYRO_OBJS[qnsid])
749 -
750 -def ns_get_proxy(nsid, defaultnsgroup=_MARKER, nshost=None):
751 -    """
752 -    if nshost is None, the nameserver is found by a broadcast.
753 -    """
754 -    # resolve the Pyro object
755 -    nsgroup, nsid = ns_group_and_id(nsid, defaultnsgroup)
756 -    try:
757 -        nsd = locate_ns(nshost)
758 -        pyrouri = nsd.resolve('%s.%s' % (nsgroup, nsid))
759 -    except errors.ProtocolError as ex:
760 -        raise errors.PyroError(
761 -            'Could not connect to the Pyro name server (host: %s)' % nshost)
762 -    except errors.NamingError:
763 -        raise errors.PyroError(
764 -            'Could not get proxy for %s (not registered in Pyro), '
765 -            'you may have to restart your server-side application' % nsid)
766 -    return core.getProxyForURI(pyrouri)
767 -
768 -def get_proxy(pyro_uri):
769 -    """get a proxy for the passed pyro uri without using a nameserver
770 -    """
771 -    return core.getProxyForURI(pyro_uri)
772 -
773 -def set_pyro_log_threshold(level):
774 -    pyrologger = logging.getLogger('Pyro.%s' % str(id(util.Log)))
775 -    # remove handlers so only the root handler is used
776 -    pyrologger.handlers = []
777 -    pyrologger.setLevel(level)
diff --git a/logilab/common/xmlrpcutils.py b/logilab/common/xmlrpcutils.py
@@ -1,131 +0,0 @@
778 -# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
779 -# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
780 -#
781 -# This file is part of logilab-common.
782 -#
783 -# logilab-common is free software: you can redistribute it and/or modify it under
784 -# the terms of the GNU Lesser General Public License as published by the Free
785 -# Software Foundation, either version 2.1 of the License, or (at your option) any
786 -# later version.
787 -#
788 -# logilab-common is distributed in the hope that it will be useful, but WITHOUT
789 -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
790 -# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
791 -# details.
792 -#
793 -# You should have received a copy of the GNU Lesser General Public License along
794 -# with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
795 -"""XML-RPC utilities."""
796 -__docformat__ = "restructuredtext en"
797 -
798 -import xmlrpclib
799 -from base64 import encodestring
800 -#from cStringIO import StringIO
801 -
802 -ProtocolError = xmlrpclib.ProtocolError
803 -
804 -## class BasicAuthTransport(xmlrpclib.Transport):
805 -##     def __init__(self, username=None, password=None):
806 -##         self.username = username
807 -##         self.password = password
808 -##         self.verbose = None
809 -##         self.has_ssl = httplib.__dict__.has_key("HTTPConnection")
810 -
811 -##     def request(self, host, handler, request_body, verbose=None):
812 -##         # issue XML-RPC request
813 -##         if self.has_ssl:
814 -##             if host.startswith("https:"): h = httplib.HTTPSConnection(host)
815 -##             else: h = httplib.HTTPConnection(host)
816 -##         else: h = httplib.HTTP(host)
817 -
818 -##         h.putrequest("POST", handler)
819 -
820 -##         # required by HTTP/1.1
821 -##         if not self.has_ssl: # HTTPConnection already does 1.1
822 -##             h.putheader("Host", host)
823 -##         h.putheader("Connection", "close")
824 -
825 -##         if request_body: h.send(request_body)
826 -##         if self.has_ssl:
827 -##             response = h.getresponse()
828 -##             if response.status != 200:
829 -##                 raise xmlrpclib.ProtocolError(host + handler,
830 -##                                               response.status,
831 -##                                               response.reason,
832 -##                                               response.msg)
833 -##             file = response.fp
834 -##         else:
835 -##             errcode, errmsg, headers = h.getreply()
836 -##             if errcode != 200:
837 -##                 raise xmlrpclib.ProtocolError(host + handler, errcode,
838 -##                                               errmsg, headers)
839 -
840 -##             file = h.getfile()
841 -
842 -##         return self.parse_response(file)
843 -
844 -
845 -
846 -class AuthMixin:
847 -    """basic http authentication mixin for xmlrpc transports"""
848 -
849 -    def __init__(self, username, password, encoding):
850 -        self.verbose = 0
851 -        self.username = username
852 -        self.password = password
853 -        self.encoding = encoding
854 -
855 -    def request(self, host, handler, request_body, verbose=0):
856 -        """issue XML-RPC request"""
857 -        h = self.make_connection(host)
858 -        h.putrequest("POST", handler)
859 -        # required by XML-RPC
860 -        h.putheader("User-Agent", self.user_agent)
861 -        h.putheader("Content-Type", "text/xml")
862 -        h.putheader("Content-Length", str(len(request_body)))
863 -        h.putheader("Host", host)
864 -        h.putheader("Connection", "close")
865 -        # basic auth
866 -        if self.username is not None and self.password is not None:
867 -            h.putheader("AUTHORIZATION", "Basic %s" % encodestring(
868 -                "%s:%s" % (self.username, self.password)).replace("\012", ""))
869 -        h.endheaders()
870 -        # send body
871 -        if request_body:
872 -            h.send(request_body)
873 -        # get and check reply
874 -        errcode, errmsg, headers = h.getreply()
875 -        if errcode != 200:
876 -            raise ProtocolError(host + handler, errcode, errmsg, headers)
877 -        file = h.getfile()
878 -##         # FIXME: encoding ??? iirc, this fix a bug in xmlrpclib but...
879 -##         data = h.getfile().read()
880 -##         if self.encoding != 'UTF-8':
881 -##             data = data.replace("version='1.0'",
882 -##                                 "version='1.0' encoding='%s'" % self.encoding)
883 -##         result = StringIO()
884 -##         result.write(data)
885 -##         result.seek(0)
886 -##         return self.parse_response(result)
887 -        return self.parse_response(file)
888 -
889 -class BasicAuthTransport(AuthMixin, xmlrpclib.Transport):
890 -    """basic http authentication transport"""
891 -
892 -class BasicAuthSafeTransport(AuthMixin, xmlrpclib.SafeTransport):
893 -    """basic https authentication transport"""
894 -
895 -
896 -def connect(url, user=None, passwd=None, encoding='ISO-8859-1'):
897 -    """return an xml rpc server on <url>, using user / password if specified
898 -    """
899 -    if user or passwd:
900 -        assert user and passwd is not None
901 -        if url.startswith('https://'):
902 -            transport = BasicAuthSafeTransport(user, passwd, encoding)
903 -        else:
904 -            transport = BasicAuthTransport(user, passwd, encoding)
905 -    else:
906 -        transport = None
907 -    server = xmlrpclib.ServerProxy(url, transport, encoding=encoding)
908 -    return server