[Python-apps-commits] r3763 - in packages/sinntp/trunk (8 files)
pl-guest at users.alioth.debian.org
pl-guest at users.alioth.debian.org
Thu Sep 17 19:02:37 UTC 2009
Date: Thursday, September 17, 2009 @ 19:02:35
Author: pl-guest
Revision: 3763
sinntp: cleaning up the mess after svn-inject without -o option, sorry!
Modified:
packages/sinntp/trunk/debian/ (properties)
Deleted:
packages/sinntp/trunk/doc/
packages/sinntp/trunk/nntp-get
packages/sinntp/trunk/nntp-list
packages/sinntp/trunk/nntp-pull
packages/sinntp/trunk/nntp-push
packages/sinntp/trunk/plugins.py
packages/sinntp/trunk/sinntp
Property changes on: packages/sinntp/trunk/debian
___________________________________________________________________
Added: mergeWithUpstream
+ 1
Deleted: packages/sinntp/trunk/nntp-get
===================================================================
--- packages/sinntp/trunk/nntp-get 2009-09-17 18:45:27 UTC (rev 3762)
+++ packages/sinntp/trunk/nntp-get 2009-09-17 19:02:35 UTC (rev 3763)
@@ -1,2 +0,0 @@
-#!/bin/sh
-exec "${0%/*}/sinntp" "${0##*-}" "$@"
Deleted: packages/sinntp/trunk/nntp-list
===================================================================
--- packages/sinntp/trunk/nntp-list 2009-09-17 18:45:27 UTC (rev 3762)
+++ packages/sinntp/trunk/nntp-list 2009-09-17 19:02:35 UTC (rev 3763)
@@ -1,2 +0,0 @@
-#!/bin/sh
-exec "${0%/*}/sinntp" "${0##*-}" "$@"
Deleted: packages/sinntp/trunk/nntp-pull
===================================================================
--- packages/sinntp/trunk/nntp-pull 2009-09-17 18:45:27 UTC (rev 3762)
+++ packages/sinntp/trunk/nntp-pull 2009-09-17 19:02:35 UTC (rev 3763)
@@ -1,2 +0,0 @@
-#!/bin/sh
-exec "${0%/*}/sinntp" "${0##*-}" "$@"
Deleted: packages/sinntp/trunk/nntp-push
===================================================================
--- packages/sinntp/trunk/nntp-push 2009-09-17 18:45:27 UTC (rev 3762)
+++ packages/sinntp/trunk/nntp-push 2009-09-17 19:02:35 UTC (rev 3763)
@@ -1,2 +0,0 @@
-#!/bin/sh
-exec "${0%/*}/sinntp" "${0##*-}" "$@"
Deleted: packages/sinntp/trunk/plugins.py
===================================================================
--- packages/sinntp/trunk/plugins.py 2009-09-17 18:45:27 UTC (rev 3762)
+++ packages/sinntp/trunk/plugins.py 2009-09-17 19:02:35 UTC (rev 3763)
@@ -1,30 +0,0 @@
-# encoding=UTF-8
-
-# Copyright © 2008, 2009
-# Piotr Lewandowski <piotr.lewandowski at gmail.com>,
-# Jakub Wilk <ubanus at users.sf.net>.
-#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License, version 2, as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-
-def debug(*args, **kwargs):
- print 'debug(*%r, **%r)' % (args, kwargs)
-
-def strip_headers(headers = 'To,Cc,Bcc', message = None):
- headers = headers.split(',')
- for header in headers:
- del message[header]
- return message
-
-def mimify(type = 'text/plain', charset = 'US-ASCII', message = None):
- if 'Content-Type' not in message:
- message['Content-Type'] = '%(type)s; charset=%(charset)s' % locals()
- return message
-
-# vim:ts=4 sw=4 et
Deleted: packages/sinntp/trunk/sinntp
===================================================================
--- packages/sinntp/trunk/sinntp 2009-09-17 18:45:27 UTC (rev 3762)
+++ packages/sinntp/trunk/sinntp 2009-09-17 19:02:35 UTC (rev 3763)
@@ -1,353 +0,0 @@
-#!/usr/bin/python
-# encoding=UTF-8
-
-# Copyright © 2008, 2009
-# Piotr Lewandowski <piotr.lewandowski at gmail.com>,
-# Jakub Wilk <ubanus at users.sf.net>.
-#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License, version 2, as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-
-__author__ = ('Jakub Wilk', 'Piotr Lewandowski')
-__version__ = '1.3'
-
-from nntplib import NNTP, NNTPTemporaryError, NNTPError
-from cStringIO import StringIO
-from xdg import BaseDirectory as xdg
-import email
-import email.generator
-import errno
-import functools
-import logging
-import logging.handlers
-import mailbox
-import optparse
-import os
-import os.path
-import socket
-import sys
-
-import plugins
-
-def monkey_patch_mailbox_module():
- '''
- Work-around a bug in the `mailbox` module.
- See http://bugs.python.org/issue3228 for details.
- '''
- try:
- create_carefully = mailbox._create_carefully
- except AttributeError:
- return
- def create_carefully_666(*args, **kwargs):
- file = create_carefully(*args, **kwargs)
- mode = os.stat(file.name).st_mode & 0666
- os.chmod(file.name, mode)
- return file
- mailbox._create_carefully = create_carefully_666
-monkey_patch_mailbox_module()
-del monkey_patch_mailbox_module
-
-class Config(object):
-
- def __init__(self, hostname):
- self._hostname = hostname
- self._root = os.getenv('SINNTP_HOME')
- if self._root:
- logging.warn('$SINNTP_HOME is deprecated in favor of $XDG_DATA_HOME. See the NEWS file for details.')
- return
- self._root = os.path.expanduser('~/.sinntp/')
- if os.path.exists(self._root):
- logging.warn('$HOME/.sinntp/ is deprecated in favor of $XDG_DATA_HOME. See the NEWS file for details.')
- return
- self._root = xdg.save_data_path('sinntp')
-
- def _get_file_name(self, name):
- base_name = '%s@%s' % (name, self._hostname)
- return os.path.join(self._root, base_name)
-
- def __getitem__(self, name):
- try:
- file = open(self._get_file_name(name), 'rb')
- except IOError, ex:
- if ex.errno == errno.ENOENT:
- return 0
- raise
- try:
- return int(file.read())
- finally:
- file.close()
-
- def __setitem__(self, name, value):
- file = open(self._get_file_name(name), 'wb')
- try:
- file.write(str(value))
- finally:
- file.close()
-
-class Command(object):
-
- def get_option_parser(self):
- o = optparse.OptionParser(usage = self.__doc__.rstrip(), version = '%prog ' + __version__)
- o.add_option('-s', '--syslog', dest='syslog', action='store_true', help='use syslog for logging')
- o.add_option('-v', '--verbose', dest='verbose', action='store_true', help='be more verbose')
- o.add_option('-q', '--quiet', dest='verbose', action='store_false', help='be less verbose')
- o.add_option('-p', '--plugin', dest='plugins', action='append', metavar='PLUGIN', help='use plugin')
- o.add_option('-S', '--server', dest='server', action='store', help='specify server address')
- o.add_option('-U', '--username', dest='username', action='store', help='specify username')
- o.add_option('-P', '--password', dest='password', action='store', help='specify password')
- o.add_option('-t', '--timeout', dest='timeout', action='store', type='int', help='specify connection timeout')
- return o
-
- def __init__(self, argv):
- oparser = self.get_option_parser()
- self.options, self.args = oparser.parse_args(argv)
- try:
- self.command_name = self.args.pop(0)
- except IndexError:
- oparser.error('A command is expected')
- self.plugins = []
- for spec in self.options.plugins or ():
- spec = spec.split(':')
- name = spec.pop(0)
- args = [arg for arg in spec if '=' not in arg]
- kwargs = dict(arg.split('=', 1) for arg in spec if '=' in arg)
- self.plugins += functools.partial(plugins.__dict__[name], *args, **kwargs),
- self.oparser = oparser
-
- def __call__(self):
- pass
-
-class Pull(Command):
- '''
- nntp-pull [options] groupname[>filename] [groupname[>filename] ...]
- '''
-
- def get_option_parser(self):
- o = Command.get_option_parser(self)
- o.add_option('--limit', dest='limit', type='int', action='store', metavar='N', help='pull at most N messages')
- o.add_option('--reget', dest='reget', action='store_true', help='start from the first available message')
- return o
-
- def __init__(self, argv):
- Command.__init__(self, argv)
- if not self.args:
- self.oparser.error('At least one group name is required')
- self.groups = self.args
- del self.args
-
- def fetch(self, connection, group_name, start):
- logging.info('Looking for group %r.', group_name)
- response, count, first, last, name = connection.group(group_name)
- count, first, last = (int(x) for x in (count, first, last))
- i = max(start, first)
- count = max(last - i + 1, 0)
- logging.info('%(count)s message%(plural)s to download.' % dict(
- count = count if count else 'No',
- plural = 's' if count != 1 else ''
- ))
- while i <= last:
- try:
- connection.stat(str(i))
- except NNTPTemporaryError, e:
- i += 1
- else:
- break
- else:
- return
- no = str(i)
- while 1:
- _, _, message_id, body = connection.article(no)
- logging.debug('Reading message %s.', message_id)
- yield int(no), body
- try:
- _, no, _ = connection.next()
- except NNTPTemporaryError, ex:
- if ex.response.startswith('421'):
- break
- raise
-
- def __call__(self, connection):
- config = Config(connection.host)
- for group in self.groups:
- if '>' in group:
- group, mbox_name = group.split('>', 1)
- else:
- mbox_name = group
- mbox = None
- atime = None
- mode = None
- last = None
- start = config[group] if not self.options.reget else 0
- if self.options.limit is not None:
- _, _, _, end, _ = connection.group(group)
- start = max(start, int(end) - self.options.limit + 1)
- try:
- for no, message in self.fetch(connection, group, start):
- if mbox is None:
- mbox = mailbox.mbox(mbox_name, create=True)
- mbox.lock()
- stat = os.stat(mbox_name)
- atime = stat.st_atime
- mode = stat.st_mode
- if not (message and message[-1].endswith('\n')):
- message += ['']
- message = '\n'.join(message)
- message = email.message_from_string(message)
- for plugin in self.plugins:
- message = plugin(message = message)
- if message is None:
- break
- if message is not None:
- mbox.add(message)
- last = no
- finally:
- if mbox is not None:
- mbox.close()
- if atime is not None:
- mtime = os.stat(mbox_name).st_mtime
- os.utime(mbox_name, (atime, mtime))
- if mode is not None:
- os.chmod(mbox_name, mode)
- if last is not None:
- config[group] = last + 1
-
-class Push(Command):
- '''
- nntp-push [options] [newsgroups...]
- '''
-
- def __call__(self, connection):
- message = email.message_from_file(sys.stdin)
- if not 'Newsgroups' in message and self.args:
- message['Newsgroups'] = ','.join(self.args)
- for plugin in self.plugins:
- message = plugin(message = message)
- buffer = StringIO()
- generator = email.generator.Generator(buffer, mangle_from_=False)
- generator.flatten(message)
- buffer.seek(0)
- connection.post(buffer)
-
-class Get(Command):
- '''
- nntp-get message-id
- '''
-
- def __init__(self, argv):
- Command.__init__(self, argv)
- if len(self.args) != 1:
- self.oparser.error('A single message-id is required')
- [self.message_id] = self.args
- if '@' not in self.message_id:
- self.oparser.error('Message-id is malformed (\'@\' is missing)')
- if self.message_id[0] + self.message_id[-1] != '<>':
- self.message_id = '<%s>' % self.message_id
- del self.args
-
- def __call__(self, connection):
- logging.debug('Reading message %s.', self.message_id)
- _, _, _, message = connection.article(self.message_id)
- message = '\n'.join(message)
- print message
-
-class List(Command):
- '''
- nntp-list
- '''
-
- def __init__(self, argv):
- Command.__init__(self, argv)
- if len(self.args) != 0:
- self.oparser.error('This command takes no arguments')
-
- def __call__(self, connection):
- _, groups = connection.list()
- print '\n'.join(group for group, _, _, flag in groups)
-
-class BaseCommand(Command):
-
- COMMANDS = dict(
- pull = Pull,
- push = Push,
- get = Get,
- list = List,
- )
-
- __doc__ = ''.join(command.__doc__.rstrip() for command in COMMANDS.itervalues())
-
- def get_option_parser(self):
- oparser = Command.get_option_parser(self)
- oparser.disable_interspersed_args()
- return oparser
-
- def __init__(self, argv):
- Command.__init__(self, argv)
- try:
- self.command_class = self.COMMANDS[self.command_name]
- except KeyError:
- self.oparser.error('Unknown command: %r.' % self.command_name)
- sys.argv[0] = 'nntp-%s' % self.command_name
-
-def show_usage():
- sys.stderr.write('Usage: \n')
- for command in COMMANDS.itervalues():
- sys.stderr.write(' %s\n' % command.__doc__.strip())
- sys.exit(1)
-
-def setup_logging(syslog, verbose):
- logger = logging.getLogger()
- format = '%(message)s'
- if not syslog:
- handler = logging.StreamHandler()
- else:
- handler = logging.handlers.SysLogHandler(
- '/dev/log',
- facility = logging.handlers.SysLogHandler.LOG_NEWS
- )
- format = ''.join((sys.argv[0], '[%(process)d]: ', format))
- formatter = logging.Formatter(format, None)
- handler.setFormatter(formatter)
- logger.addHandler(handler)
- level = {
- True: logging.DEBUG,
- None: logging.INFO,
- False: logging.ERROR,
- }.get(verbose)
- logger.setLevel(level)
-
-if __name__ == '__main__':
- argv = sys.argv[1:]
- base_command = BaseCommand(argv)
- command = base_command.command_class(argv)
- setup_logging(command.options.syslog, command.options.verbose)
- host = command.options.server or os.getenv('NNTPSERVER') or \
- (os.path.exists('/etc/news/server') and file('/etc/news/server').readline().strip())
- if not host:
- sys.stderr.write('NNTP server is not specified.\n')
- sys.exit(2)
- socket.setdefaulttimeout(command.options.timeout)
- try:
- logging.info('Connecting to %r...', host)
- connection = NNTP(host, user = command.options.username, password = command.options.password)
- except socket.error, e:
- logging.error('Could not connect to %r: %s', host, e.message)
- sys.exit(3)
- except NNTPError, e:
- logging.error('%r returned an error: %s', host, e.message)
- sys.exit(4)
- try:
- command(connection)
- except NNTPError, e:
- logging.error('NNTP error: ' + e.message)
- sys.exit(4)
- finally:
- connection.quit()
- logging.info('Connection to %r closed.', host)
-
-# vim:ts=4 sw=4 et
More information about the Python-apps-commits
mailing list