Lines Matching +full:file +full:- +full:lines

2 - RFC 977: Network News Transfer Protocol
3 - RFC 2980: Common NNTP Extensions
4 - RFC 3977: Network News Transfer Protocol (version 2)
13 >>> resp, subs = s.xhdr('subject', '{0}-{1}'.format(first, last))
20 To post an article from a file:
21 >>> f = open(filename, 'rb') # file containing article, including header
34 # - all commands are encoded as UTF-8 data (using the "surrogateescape"
36 # - all responses are decoded as UTF-8 data (using the "surrogateescape"
38 # - the `file` argument to various methods is keyword-only
40 # - NNTP.date() returns a datetime object
41 # - NNTP.newgroups() and NNTP.newnews() take a datetime (or date) object,
43 # - NNTP.newgroups() and NNTP.list() return a list of GroupInfo named tuples
44 # - NNTP.descriptions() returns a dict mapping group names to descriptions
45 # - NNTP.xover() returns a list of dicts mapping field names (header or metadata)
47 # - NNTP.article(), NNTP.head() and NNTP.body() return a (response, ArticleInfo)
49 # - the "internal" methods have been marked private (they now start with
53 # - automatic querying of capabilities at connect
54 # - New method NNTP.getcapabilities()
55 # - New method NNTP.over()
56 # - New helper function decode_header()
57 # - NNTP.post() and NNTP.ihave() accept file objects, bytes-like objects and
58 # arbitrary iterables yielding lines.
59 # - An extensive test suite :-)
62 # - return structured data (GroupInfo etc.) everywhere
63 # - support HDR
92 # reading arbitrary length lines. RFC 3977 limits NNTP line length to
121 """Response does not begin with [1-5]"""
137 '211', # LISTGROUP (also not multi-line with GROUP)
151 "subject", "from", "date", "message-id", "references", ":bytes", ":lines"]
156 'lines': ':lines',
166 ['number', 'message_id', 'lines'])
172 and decodes it as a (possibly non-ASCII) readable value."""
181 def _parse_overview_fmt(lines): argument
187 for line in lines:
206 def _parse_overview(lines, fmt, data_process_func=None): argument
211 for line in lines:
224 # Non-default header names are included in full in the response
241 time_str = date_str[-6:]
242 date_str = date_str[:-6]
246 year = int(date_str[:-4])
247 month = int(date_str[-4:-2])
248 day = int(date_str[-2:])
249 # RFC 3977 doesn't say how to interpret 2-char years. Assume that
287 - sock: Socket to wrap
288 - context: SSL context to use for the encrypted connection
290 - sock: New, encrypted socket.
300 # UTF-8 is the character set for all NNTP commands and responses: they
303 # However, some multi-line data blocks can contain arbitrary bytes (for
304 # example, latin-1 or utf-16 data in the body of a message). Commands
307 # Furthermore, since there could be non-compliant servers out there,
309 # and easy round-tripping. This could be useful for some applications
312 encoding = 'utf-8'
319 - host: hostname to connect to
320 - port: port to connect to (default the standard NNTP port)
321 - user: username to authenticate with
322 - password: password to use with username
323 - readermode: if true, send 'mode reader' command after
325 - usenetrc: allow loading username and password from ~/.netrc file
327 - timeout: timeout (in seconds) used for socket connections
331 reader-specific commands, such as `group'. If you get
338 self.file = None
340 self.file = self.sock.makefile("rwb")
345 if self.file:
346 self.file.close()
388 is_connected = lambda: hasattr(self, "file")
400 raise ValueError('Non-blocking socket (timeout=0) is not supported')
439 2: also print raw lines read and sent before stripping CR/LF"""
446 The `line` must be a bytes-like object."""
450 self.file.write(line)
451 self.file.flush()
464 line = self.file.readline(_MAXLINE +1)
471 if line[-2:] == _CRLF:
472 line = line[:-2]
473 elif line[-1:] in _CRLF:
474 line = line[:-1]
493 def _getlongresp(self, file=None): argument
497 Returns a (response, lines) tuple where `response` is a unicode
498 string and `lines` is a list of bytes objects.
499 If `file` is a file-like object, it must be open in binary mode.
504 # If a string was passed then open a file with that name
505 if isinstance(file, (str, bytes)):
506 openedFile = file = open(file, "wb")
512 lines = []
513 if file is not None:
514 # XXX lines = None instead?
522 file.write(line)
531 lines.append(line)
533 # If this method created the file, then it must close it
537 return resp, lines
545 def _longcmd(self, line, file=None): argument
549 return self._getlongresp(file)
551 def _longcmdstring(self, line, file=None): argument
553 Same as _longcmd() and _getlongresp(), except that the returned `lines`
557 resp, list = self._getlongresp(file)
569 resp, lines = self._longcmdstring("LIST OVERVIEW.FMT")
574 fmt = _parse_overview_fmt(lines)
578 def _grouplist(self, lines): argument
579 # Parse lines into "group last first flag"
580 return [GroupInfo(*line.split()) for line in lines]
585 - resp: server response if successful
586 - caps: a dictionary mapping capability names to lists of tokens
590 resp, lines = self._longcmdstring("CAPABILITIES")
591 for line in lines:
596 def newgroups(self, date, *, file=None): argument
598 - date: a date or datetime object
600 - resp: server response if successful
601 - list: list of newsgroup names
609 resp, lines = self._longcmdstring(cmd, file)
610 return resp, self._grouplist(lines)
612 def newnews(self, group, date, *, file=None): argument
614 - group: group name or '*'
615 - date: a date or datetime object
617 - resp: server response if successful
618 - list: list of message ids
626 return self._longcmdstring(cmd, file)
628 def list(self, group_pattern=None, *, file=None): argument
630 - group_pattern: a pattern indicating which groups to query
631 - file: Filename string or file object to store the result in
633 - resp: server response if successful
634 - list: list of (group, last, first, flag) (strings)
640 resp, lines = self._longcmdstring(command, file)
641 return resp, self._grouplist(lines)
646 resp, lines = self._longcmdstring('LIST NEWSGROUPS ' + group_pattern)
651 resp, lines = self._longcmdstring('XGTITLE ' + group_pattern)
653 for raw_line in lines:
685 - group: the group name
687 - resp: server response if successful
688 - count: number of articles
689 - first: first article number
690 - last: last article number
691 - name: the group name
709 def help(self, *, file=None): argument
711 - file: Filename string or file object to store the result in
713 - resp: server response if successful
714 - list: list of strings returned by the server in response to the
717 return self._longcmdstring('HELP', file)
736 - message_spec: article number or message id (if not specified,
739 - resp: server response if successful
740 - art_num: the article number
741 - message_id: the message id
756 def _artcmd(self, line, file=None): argument
758 resp, lines = self._longcmd(line, file)
760 return resp, ArticleInfo(art_num, message_id, lines)
762 def head(self, message_spec=None, *, file=None): argument
764 - message_spec: article number or message id
765 - file: filename string or file object to store the headers in
767 - resp: server response if successful
768 - ArticleInfo: (article number, message id, list of header lines)
774 return self._artcmd(cmd, file)
776 def body(self, message_spec=None, *, file=None): argument
778 - message_spec: article number or message id
779 - file: filename string or file object to store the body in
781 - resp: server response if successful
782 - ArticleInfo: (article number, message id, list of body lines)
788 return self._artcmd(cmd, file)
790 def article(self, message_spec=None, *, file=None): argument
792 - message_spec: article number or message id
793 - file: filename string or file object to store the article in
795 - resp: server response if successful
796 - ArticleInfo: (article number, message id, list of article lines)
802 return self._artcmd(cmd, file)
806 - resp: server response if successful
810 def xhdr(self, hdr, str, *, file=None): argument
812 - hdr: the header type (e.g. 'subject')
813 - str: an article nr, a message id, or a range nr1-nr2
814 - file: Filename string or file object to store the result in
816 - resp: server response if successful
817 - list: list of (nr, value) strings
819 pat = re.compile('^([0-9]+) ?(.*)\n?')
820 resp, lines = self._longcmdstring('XHDR {0} {1}'.format(hdr, str), file)
824 return resp, [remove_number(line) for line in lines]
826 def xover(self, start, end, *, file=None): argument
828 - start: start of range
829 - end: end of range
830 - file: Filename string or file object to store the result in
832 - resp: server response if successful
833 - list: list of dicts containing the response fields
835 resp, lines = self._longcmdstring('XOVER {0}-{1}'.format(start, end),
836 file)
838 return resp, _parse_overview(lines, fmt)
840 def over(self, message_spec, *, file=None): argument
843 - message_spec:
844 - either a message id, indicating the article to fetch
846 - or a (start, end) tuple, indicating a range of article numbers;
849 - or None, indicating the current article number must be used
850 - file: Filename string or file object to store the result in
852 - resp: server response if successful
853 - list: list of dicts containing the response fields
860 cmd += ' {0}-{1}'.format(start, end or '')
863 resp, lines = self._longcmdstring(cmd, file)
865 return resp, _parse_overview(lines, fmt)
870 - resp: server response if successful
871 - date: datetime object
892 # - we don't want additional CRLF if the file or iterable is already
894 # - we don't want a spurious flush() after each line is written
900 self.file.write(line)
901 self.file.write(b".\r\n")
902 self.file.flush()
907 - data: bytes object, iterable or file containing the article
909 - resp: server response if successful"""
914 - message_id: message-id of the article
915 - data: file containing the article
917 - resp: server response if successful
923 if self.file:
924 self.file.close()
925 del self.file
931 - resp: server response if successful"""
995 - context: SSL context to use for the encrypted connection
1005 self.file.close()
1007 self.file = self.sock.makefile("rwb")
1049 nntplib built-in demo - display the latest articles in a newsgroup""")
1050 parser.add_argument('-g', '--group', default='gmane.comp.python.general',
1052 parser.add_argument('-s', '--server', default='news.gmane.io',
1054 parser.add_argument('-p', '--port', default=-1, type=int,
1056 parser.add_argument('-n', '--nb-articles', default=10, type=int,
1058 parser.add_argument('-S', '--ssl', action='store_true', default=False,
1064 if port == -1:
1068 if port == -1:
1080 s = s[:lim - 4] + "..."
1083 first = str(int(last) - args.nb_articles + 1)
1088 lines = int(over[':lines']) variable
1090 artnum, cut(author, 20), cut(subject, 42), lines)