xbot.plugins.ssh 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
demo/lib/__init__.py ADDED
File without changes
demo/lib/testbed.py ADDED
@@ -0,0 +1,48 @@
1
+ from typing import Union
2
+
3
+ from xbot.framework import testbed
4
+ from xbot.plugins.ssh.ssh import SSHConnection
5
+ from xbot.plugins.ssh.sftp import SFTPConnection
6
+
7
+
8
+ class TestBed(testbed.TestBed):
9
+ """
10
+ TestBed for ssh demo.
11
+ """
12
+ def __init__(self, filepath: str):
13
+ """
14
+ :param filepath: testbed filepath.
15
+ """
16
+ super().__init__(filepath)
17
+ self._conns = {
18
+ 'ssh': {},
19
+ 'sftp': {}
20
+ }
21
+
22
+ def get_conn(
23
+ self,
24
+ typ: str,
25
+ role: str
26
+ ) -> Union[SSHConnection, SFTPConnection]:
27
+ """
28
+ Get specific connection to the specified role.
29
+
30
+ :param typ: connection type, 'ssh' or 'sftp'.
31
+ :param role: user role.
32
+ """
33
+ typs = ('ssh', 'sftp')
34
+ if typ not in typs:
35
+ raise ValueError(f'Invalid connection type: {typ}, should be one of {typs}.')
36
+ for user in self.get('host.users'):
37
+ if user['role'] == role:
38
+ if role not in self._conns[typ]:
39
+ conn = SSHConnection() if typ == 'ssh' else SFTPConnection()
40
+ conn.connect(self.get('host.ip'),
41
+ user['name'],
42
+ user['password'],
43
+ port=self.get('host.sshport'))
44
+ self._conns[typ][role] = conn
45
+ return self._conns[typ][role]
46
+ raise ValueError(f'No such user: role={role}')
47
+
48
+
demo/lib/testcase.py ADDED
@@ -0,0 +1,15 @@
1
+ from xbot.framework import testcase
2
+
3
+ from .testbed import TestBed
4
+
5
+
6
+ class TestCase(testcase.TestCase):
7
+ """
8
+ TestCase for ssh demo.
9
+ """
10
+ @property
11
+ def testbed(self) -> TestBed:
12
+ """
13
+ TestBed instance.
14
+ """
15
+ return self.__testbed
File without changes
@@ -0,0 +1,99 @@
1
+ import os
2
+ import shutil
3
+
4
+ from xbot.framework.utils import assertx
5
+
6
+ from lib.testcase import TestCase
7
+
8
+
9
+ class tc_sftp(TestCase):
10
+ """
11
+ Testcase using SFTPConnection.
12
+ """
13
+ TIMEOUT = 60
14
+ FAILFAST = True
15
+ TAGS = ['sftp']
16
+
17
+ def setup(self):
18
+ """
19
+ Prepare test environment.
20
+ """
21
+ self.sftp = self.testbed.get_conn('sftp', 'normal')
22
+ self.lhome = os.environ.get('HOME') or os.environ['HOMEPATH']
23
+ self.lputdir = os.path.join(self.lhome, 'lputdir')
24
+ self.lgetdir = os.path.join(self.lhome, 'lgetdir')
25
+ self.rputdir = '/tmp/rputgetdir'
26
+ self.rgetdir = self.rputdir
27
+ for d in (self.lputdir, self.lgetdir):
28
+ if os.path.exists(d):
29
+ shutil.rmtree(d)
30
+ self.sftp.makedirs(self.rputdir)
31
+ os.makedirs(os.path.join(self.lputdir, 'dir', 'subdir'))
32
+ os.system('whoami > %s' % os.path.join(self.lputdir, 'file'))
33
+ os.system('whoami > %s' % os.path.join(self.lputdir, 'dir', 'subfile'))
34
+
35
+ def step1(self):
36
+ """
37
+ Test `putdir` method.
38
+ """
39
+ l = os.path.join(self.lputdir, 'dir')
40
+ self.sftp.putdir(l, self.rputdir)
41
+ p1 = self.sftp.join(self.rputdir, 'dir', 'subdir')
42
+ assertx(self.sftp.exists(p1), '==', True)
43
+ p2 = self.sftp.join(self.rputdir, 'dir', 'subfile')
44
+ assertx(self.sftp.exists(p2), '==', True)
45
+
46
+ def step2(self):
47
+ """
48
+ Test `putfile` method.
49
+ """
50
+ l = os.path.join(self.lputdir, 'file')
51
+ self.sftp.putfile(l, self.rputdir)
52
+ p1 = self.sftp.join(self.rputdir, 'file')
53
+ assertx(self.sftp.exists(p1), '==', True)
54
+ # rename
55
+ self.sftp.putfile(l, self.rputdir, 'newfile')
56
+ p2 = self.sftp.join(self.rputdir, 'newfile')
57
+ assertx(self.sftp.exists(p2), '==', True)
58
+
59
+ def step3(self):
60
+ """
61
+ Test `getdir` method.
62
+ """
63
+ r = self.sftp.join(self.rgetdir, 'dir')
64
+ self.sftp.getdir(r, self.lgetdir)
65
+ p1 = os.path.join(self.lgetdir, 'dir', 'subdir')
66
+ assertx(os.path.exists(p1), '==', True)
67
+ p2 = os.path.join(self.lgetdir, 'dir', 'subfile')
68
+ assertx(os.path.exists(p2), '==', True)
69
+
70
+ def step4(self):
71
+ """
72
+ Test `getfile` method.
73
+ """
74
+ r = self.sftp.join(self.rgetdir, 'file')
75
+ self.sftp.getfile(r, self.lgetdir)
76
+ p1 = os.path.join(self.lgetdir, 'file')
77
+ assertx(os.path.exists(p1), '==', True)
78
+ # rename
79
+ self.sftp.getfile(r, self.lgetdir, 'newfile')
80
+ p2 = os.path.join(self.lgetdir, 'newfile')
81
+ assertx(os.path.exists(p2), '==', True)
82
+
83
+ def step5(self):
84
+ """
85
+ Test `open` method.
86
+ """
87
+ p = self.sftp.join(self.rputdir, 'file')
88
+ with self.sftp.open(p, 'w') as fp:
89
+ fp.write('xbot')
90
+ with self.sftp.open(p, 'r') as fp:
91
+ assertx(fp.read().decode('utf-8'), '==', 'xbot')
92
+
93
+ def teardown(self):
94
+ """
95
+ Clean up test environment.
96
+ """
97
+ shutil.rmtree(self.lputdir)
98
+ shutil.rmtree(self.lgetdir)
99
+
@@ -0,0 +1,73 @@
1
+ from lib.testcase import TestCase
2
+
3
+
4
+ class tc_ssh(TestCase):
5
+ """
6
+ Testcase using SSHConnection.
7
+ """
8
+ TIMEOUT = 60
9
+ FAILFAST = True
10
+ TAGS = ['ssh']
11
+
12
+ def setup(self):
13
+ """
14
+ Prepare test environment.
15
+ """
16
+ self.ssh = self.testbed.get_conn('ssh', 'normal')
17
+
18
+ def step1(self):
19
+ """
20
+ Execute command `whoami`, expect `name` of the normal user.
21
+ """
22
+ username = self.testbed.get("host.users[?role=='normal']")[0]['name']
23
+ self.ssh.exec('whoami', expect=username)
24
+
25
+ def step2(self):
26
+ """
27
+ Execute command `sudo whoami`, expect `root`.
28
+ """
29
+ self.ssh.sudo('whoami', expect='root')
30
+
31
+ def step3(self):
32
+ """
33
+ Execute a interactive command.
34
+ """
35
+ self.ssh.exec("read -p 'input: '", prompts={'input:': 'hello'})
36
+
37
+ def step4(self):
38
+ """
39
+ Execute a command and expect no error.
40
+ """
41
+ self.ssh.exec('ls /tmp', expect=0)
42
+
43
+ def step5(self):
44
+ """
45
+ Execute a command and expect return code is 2.
46
+ """
47
+ self.ssh.exec('ls /errpath', expect=2)
48
+
49
+ def step5(self):
50
+ """
51
+ Execute a command and expect nothing.
52
+ """
53
+ self.ssh.exec('ls /tmp', expect=None)
54
+ self.ssh.exec('ls /errpath', expect=None)
55
+
56
+ def step6(self):
57
+ """
58
+ Execute a command and expect a specific output.
59
+ """
60
+ self.ssh.exec('echo hello', expect='hello')
61
+
62
+ def step7(self):
63
+ """
64
+ Execute a command with cd context manager.
65
+ """
66
+ with self.ssh.cd('/tmp'):
67
+ self.ssh.exec('pwd', expect='/tmp')
68
+
69
+ def teardown(self):
70
+ """
71
+ Clean up test environment.
72
+ """
73
+ pass
tests/__init__.py ADDED
File without changes
tests/run.py ADDED
@@ -0,0 +1,39 @@
1
+ """
2
+ Run tests.
3
+ """
4
+
5
+ import unittest
6
+ import argparse
7
+
8
+ from pathlib import Path
9
+
10
+ from test_ssh import TestSSHConnection
11
+ from test_sftp import TestSFTPConnection
12
+
13
+
14
+ def create_parser() -> argparse.ArgumentParser:
15
+ parser = argparse.ArgumentParser()
16
+ parser.add_argument('-H', '--host', required=True,
17
+ help='hostname or ip to test.')
18
+ parser.add_argument('-u', '--user', required=True,
19
+ help='username for host.')
20
+ parser.add_argument('-p', '--password', required=True,
21
+ help='password for host.')
22
+ parser.add_argument('-P', '--port', type=int, default=22,
23
+ help='ssh port for host.')
24
+ return parser
25
+
26
+
27
+ if __name__ == '__main__':
28
+ args = create_parser().parse_args()
29
+ TestSSHConnection.HOST = args.host
30
+ TestSSHConnection.USER = args.user
31
+ TestSSHConnection.PWD = args.password
32
+ TestSSHConnection.PORT = args.port
33
+ TestSFTPConnection.HOST = args.host
34
+ TestSFTPConnection.USER = args.user
35
+ TestSFTPConnection.PWD = args.password
36
+ TestSFTPConnection.PORT = args.port
37
+ startdir = Path(__file__).parent
38
+ testsuit = unittest.TestLoader().discover(startdir)
39
+ unittest.TextTestRunner(verbosity=2).run(testsuit)
tests/test_sftp.py ADDED
@@ -0,0 +1,88 @@
1
+ # Copyright (c) 2022-2023, zhaowcheng <zhaowcheng@163.com>
2
+
3
+ import unittest
4
+ import shutil
5
+ import os
6
+ import sys
7
+ sys.path.append(os.path.abspath(f'{__file__}/../..'))
8
+
9
+ from xbot.plugins.ssh.sftp import SFTPConnection
10
+
11
+
12
+ class TestSFTPConnection(unittest.TestCase):
13
+
14
+ HOST = ''
15
+ PORT = 22
16
+ USER = ''
17
+ PWD = ''
18
+
19
+ sftp = SFTPConnection()
20
+
21
+ LHOME = os.environ.get('HOME') or os.environ['HOMEPATH']
22
+ LPUTDIR = os.path.join(LHOME, 'lputdir')
23
+ LGETDIR = os.path.join(LHOME, 'lgetdir')
24
+ RPUTDIR = '/tmp/rputgetdir'
25
+ RGETDIR = RPUTDIR
26
+
27
+ @classmethod
28
+ def setUpClass(cls):
29
+ cls.sftp.connect(cls.HOST, cls.USER,
30
+ cls.PWD, cls.PORT)
31
+ if not cls.sftp.exists(cls.RPUTDIR):
32
+ cls.sftp.makedirs(cls.RPUTDIR)
33
+ os.makedirs(os.path.join(cls.LPUTDIR, 'dir', 'subdir'))
34
+ os.system('whoami > %s' % os.path.join(cls.LPUTDIR, 'file'))
35
+ os.system('whoami > %s' % os.path.join(cls.LPUTDIR, 'dir', 'subfile'))
36
+
37
+ @classmethod
38
+ def tearDownClass(cls):
39
+ shutil.rmtree(cls.LPUTDIR)
40
+ shutil.rmtree(cls.LGETDIR)
41
+ cls.sftp.disconnect()
42
+
43
+ def test_01_putdir(self):
44
+ l = os.path.join(self.LPUTDIR, 'dir')
45
+ self.sftp.putdir(l, self.RPUTDIR)
46
+ p1 = self.sftp.join(self.RPUTDIR, 'dir', 'subdir')
47
+ self.assertTrue(self.sftp.exists(p1))
48
+ p2 = self.sftp.join(self.RPUTDIR, 'dir', 'subfile')
49
+ self.assertTrue(self.sftp.exists(p2))
50
+
51
+ def test_02_putfile(self):
52
+ l = os.path.join(self.LPUTDIR, 'file')
53
+ self.sftp.putfile(l, self.RPUTDIR)
54
+ p1 = self.sftp.join(self.RPUTDIR, 'file')
55
+ self.assertTrue(self.sftp.exists(p1))
56
+ # rename
57
+ self.sftp.putfile(l, self.RPUTDIR, 'newfile')
58
+ p2 = self.sftp.join(self.RPUTDIR, 'newfile')
59
+ self.assertTrue(self.sftp.exists(p2))
60
+
61
+ def test_03_getdir(self):
62
+ r = self.sftp.join(self.RGETDIR, 'dir')
63
+ self.sftp.getdir(r, self.LGETDIR)
64
+ p1 = os.path.join(self.LGETDIR, 'dir', 'subdir')
65
+ self.assertTrue(os.path.exists(p1))
66
+ p2 = os.path.join(self.LGETDIR, 'dir', 'subfile')
67
+ self.assertTrue(os.path.exists(p2))
68
+
69
+ def test_04_getfile(self):
70
+ r = self.sftp.join(self.RGETDIR, 'file')
71
+ self.sftp.getfile(r, self.LGETDIR)
72
+ p1 = os.path.join(self.LGETDIR, 'file')
73
+ self.assertTrue(os.path.exists(p1))
74
+ # rename
75
+ self.sftp.getfile(r, self.LGETDIR, 'newfile')
76
+ p2 = os.path.join(self.LGETDIR, 'newfile')
77
+ self.assertTrue(os.path.exists(p2))
78
+
79
+ def test_05_open(self):
80
+ p = self.sftp.join(self.RPUTDIR, 'file')
81
+ with self.sftp.open(p, 'a') as fp:
82
+ fp.write('xbot\n')
83
+ with self.sftp.open(p, 'r') as fp:
84
+ self.assertIn('xbot', fp.read().decode('utf-8'))
85
+
86
+
87
+ if __name__ == '__main__':
88
+ unittest.main(verbosity=2)
tests/test_ssh.py ADDED
@@ -0,0 +1,99 @@
1
+ # Copyright (c) 2022-2023, zhaowcheng <zhaowcheng@163.com>
2
+
3
+ import unittest
4
+ import doctest
5
+ import sys
6
+ import os
7
+ sys.path.append(os.path.abspath(f'{__file__}/../..'))
8
+
9
+ from xbot.plugins.ssh import ssh
10
+ from xbot.plugins.ssh.ssh import SSHConnection
11
+ from xbot.plugins.ssh.errors import SSHConnectError, SSHCommandError
12
+
13
+
14
+ def load_tests(loader, tests, ignore):
15
+ tests.addTests(doctest.DocTestSuite(ssh))
16
+ return tests
17
+
18
+
19
+ class TestSSHConnection(unittest.TestCase):
20
+
21
+ HOST = ''
22
+ PORT = 22
23
+ USER = ''
24
+ PWD = ''
25
+
26
+ conn = SSHConnection()
27
+
28
+ def setenv(self, name: str, value: str) -> None:
29
+ self.conn.exec(f'export {name}="{value}"')
30
+
31
+ def getenv(self, name: str) -> str:
32
+ return self.conn.exec(f'echo ${name}')
33
+
34
+ @classmethod
35
+ def setUpClass(cls) -> None:
36
+ cls.conn.connect(cls.HOST, cls.USER, cls.PWD, cls.PORT)
37
+
38
+ @classmethod
39
+ def tearDownClass(cls) -> None:
40
+ cls.conn.disconnect()
41
+
42
+ def test_connect_error_pwd(self):
43
+ conn = SSHConnection()
44
+ with self.assertRaises(SSHConnectError) as cm:
45
+ conn.connect(self.HOST, self.USER, self.PWD + 'shit', self.PORT)
46
+ self.assertIn('please check whether the username and password are correct',
47
+ str(cm.exception))
48
+
49
+ def test_connect_error_port(self):
50
+ conn = SSHConnection()
51
+ with self.assertRaises(SSHConnectError) as cm:
52
+ conn.connect(self.HOST, self.USER, self.PWD, self.PORT + 1000)
53
+ self.assertRegex(str(cm.exception),
54
+ r'.*please check whether the port is (opened|correct).*')
55
+
56
+ def test_connect_error_ip(self):
57
+ conn = SSHConnection()
58
+ with self.assertRaises(SSHConnectError) as cm:
59
+ conn.connect('128.0.0.1', self.USER, self.PWD, self.PORT)
60
+ self.assertIn('please check whether the network is normal',
61
+ str(cm.exception))
62
+
63
+ def test_cmd_whoami(self):
64
+ self.conn.exec('whoami', expect=self.USER)
65
+
66
+ def test_cmd_sudo(self):
67
+ self.conn.sudo('whoami', expect='root')
68
+
69
+ def test_cmd_interact(self):
70
+ self.conn.exec("read -p 'input: '", prompts={'input:': 'hello'})
71
+
72
+ def test_expect_0(self):
73
+ self.conn.exec('ls /tmp', expect=0)
74
+ with self.assertRaises(SSHCommandError):
75
+ self.conn.exec('ls /errpath', expect=0)
76
+
77
+ def test_expect_2(self):
78
+ self.conn.exec('ls /errpath', expect=2)
79
+
80
+ def test_expect_none(self):
81
+ self.conn.exec('ls /tmp', expect=None)
82
+ self.conn.exec('ls /errpath', expect=None)
83
+
84
+ def test_expect_str(self):
85
+ self.conn.exec('echo hello', expect='hello')
86
+ with self.assertRaises(SSHCommandError):
87
+ self.conn.exec('echo hello', expect='world')
88
+
89
+ def test_timeout(self):
90
+ with self.assertRaises(TimeoutError):
91
+ self.conn.exec('sleep 3', timeout=1)
92
+
93
+ def test_cmd_cd(self):
94
+ with self.conn.cd('/tmp'):
95
+ self.assertEqual(self.conn.exec('pwd'), '/tmp')
96
+
97
+
98
+ if __name__ == '__main__':
99
+ unittest.main(verbosity=2)
tests/test_utils.py ADDED
@@ -0,0 +1,18 @@
1
+ # Copyright (c) 2022-2023, zhaowcheng <zhaowcheng@163.com>
2
+
3
+ import unittest
4
+ import doctest
5
+ import sys
6
+ import os
7
+ sys.path.append(os.path.abspath(f'{__file__}/../..'))
8
+
9
+ from xbot.plugins.ssh import utils
10
+
11
+
12
+ def load_tests(loader, tests, ignore):
13
+ tests.addTests(doctest.DocTestSuite(utils))
14
+ return tests
15
+
16
+
17
+ if __name__ == '__main__':
18
+ unittest.main(verbosity=2)
venv/bin/jp.py ADDED
@@ -0,0 +1,54 @@
1
+ #!/Users/wan/CodeProjects/xbot.plugins.ssh/venv/bin/python3.6
2
+
3
+ import sys
4
+ import json
5
+ import argparse
6
+ from pprint import pformat
7
+
8
+ import jmespath
9
+ from jmespath import exceptions
10
+
11
+
12
+ def main():
13
+ parser = argparse.ArgumentParser()
14
+ parser.add_argument('expression')
15
+ parser.add_argument('-f', '--filename',
16
+ help=('The filename containing the input data. '
17
+ 'If a filename is not given then data is '
18
+ 'read from stdin.'))
19
+ parser.add_argument('--ast', action='store_true',
20
+ help=('Pretty print the AST, do not search the data.'))
21
+ args = parser.parse_args()
22
+ expression = args.expression
23
+ if args.ast:
24
+ # Only print the AST
25
+ expression = jmespath.compile(args.expression)
26
+ sys.stdout.write(pformat(expression.parsed))
27
+ sys.stdout.write('\n')
28
+ return 0
29
+ if args.filename:
30
+ with open(args.filename, 'r') as f:
31
+ data = json.load(f)
32
+ else:
33
+ data = sys.stdin.read()
34
+ data = json.loads(data)
35
+ try:
36
+ sys.stdout.write(json.dumps(
37
+ jmespath.search(expression, data), indent=4, ensure_ascii=False))
38
+ sys.stdout.write('\n')
39
+ except exceptions.ArityError as e:
40
+ sys.stderr.write("invalid-arity: %s\n" % e)
41
+ return 1
42
+ except exceptions.JMESPathTypeError as e:
43
+ sys.stderr.write("invalid-type: %s\n" % e)
44
+ return 1
45
+ except exceptions.UnknownFunctionError as e:
46
+ sys.stderr.write("unknown-function: %s\n" % e)
47
+ return 1
48
+ except exceptions.ParseError as e:
49
+ sys.stderr.write("syntax-error: %s\n" % e)
50
+ return 1
51
+
52
+
53
+ if __name__ == '__main__':
54
+ sys.exit(main())
venv/bin/rst2html.py ADDED
@@ -0,0 +1,23 @@
1
+ #!/Users/wan/CodeProjects/xbot.plugins.ssh/venv/bin/python3.6
2
+
3
+ # $Id: rst2html.py 4564 2006-05-21 20:44:42Z wiemann $
4
+ # Author: David Goodger <goodger@python.org>
5
+ # Copyright: This module has been placed in the public domain.
6
+
7
+ """
8
+ A minimal front end to the Docutils Publisher, producing HTML.
9
+ """
10
+
11
+ try:
12
+ import locale
13
+ locale.setlocale(locale.LC_ALL, '')
14
+ except:
15
+ pass
16
+
17
+ from docutils.core import publish_cmdline, default_description
18
+
19
+
20
+ description = ('Generates (X)HTML documents from standalone reStructuredText '
21
+ 'sources. ' + default_description)
22
+
23
+ publish_cmdline(writer_name='html', description=description)
venv/bin/rst2html4.py ADDED
@@ -0,0 +1,26 @@
1
+ #!/Users/wan/CodeProjects/xbot.plugins.ssh/venv/bin/python3.6
2
+
3
+ # $Id: rst2html4.py 7994 2016-12-10 17:41:45Z milde $
4
+ # Author: David Goodger <goodger@python.org>
5
+ # Copyright: This module has been placed in the public domain.
6
+
7
+ """
8
+ A minimal front end to the Docutils Publisher, producing (X)HTML.
9
+
10
+ The output conforms to XHTML 1.0 transitional
11
+ and almost to HTML 4.01 transitional (except for closing empty tags).
12
+ """
13
+
14
+ try:
15
+ import locale
16
+ locale.setlocale(locale.LC_ALL, '')
17
+ except:
18
+ pass
19
+
20
+ from docutils.core import publish_cmdline, default_description
21
+
22
+
23
+ description = ('Generates (X)HTML documents from standalone reStructuredText '
24
+ 'sources. ' + default_description)
25
+
26
+ publish_cmdline(writer_name='html4', description=description)
venv/bin/rst2html5.py ADDED
@@ -0,0 +1,34 @@
1
+ #!/Users/wan/CodeProjects/xbot.plugins.ssh/venv/bin/python3.6
2
+ # -*- coding: utf8 -*-
3
+ # :Copyright: © 2015 Günter Milde.
4
+ # :License: Released under the terms of the `2-Clause BSD license`_, in short:
5
+ #
6
+ # Copying and distribution of this file, with or without modification,
7
+ # are permitted in any medium without royalty provided the copyright
8
+ # notice and this notice are preserved.
9
+ # This file is offered as-is, without any warranty.
10
+ #
11
+ # .. _2-Clause BSD license: https://opensource.org/licenses/BSD-2-Clause
12
+ #
13
+ # Revision: $Revision: 8567 $
14
+ # Date: $Date: 2020-09-30 13:57:21 +0200 (Mi, 30. Sep 2020) $
15
+
16
+ """
17
+ A minimal front end to the Docutils Publisher, producing HTML 5 documents.
18
+
19
+ The output is also valid XML.
20
+ """
21
+
22
+ try:
23
+ import locale # module missing in Jython
24
+ locale.setlocale(locale.LC_ALL, '')
25
+ except locale.Error:
26
+ pass
27
+
28
+ from docutils.core import publish_cmdline, default_description
29
+
30
+ description = (u'Generates HTML5 documents from standalone '
31
+ u'reStructuredText sources.\n'
32
+ + default_description)
33
+
34
+ publish_cmdline(writer_name='html5', description=description)
venv/bin/rst2latex.py ADDED
@@ -0,0 +1,26 @@
1
+ #!/Users/wan/CodeProjects/xbot.plugins.ssh/venv/bin/python3.6
2
+
3
+ # $Id: rst2latex.py 5905 2009-04-16 12:04:49Z milde $
4
+ # Author: David Goodger <goodger@python.org>
5
+ # Copyright: This module has been placed in the public domain.
6
+
7
+ """
8
+ A minimal front end to the Docutils Publisher, producing LaTeX.
9
+ """
10
+
11
+ try:
12
+ import locale
13
+ locale.setlocale(locale.LC_ALL, '')
14
+ except:
15
+ pass
16
+
17
+ from docutils.core import publish_cmdline
18
+
19
+ description = ('Generates LaTeX documents from standalone reStructuredText '
20
+ 'sources. '
21
+ 'Reads from <source> (default is stdin) and writes to '
22
+ '<destination> (default is stdout). See '
23
+ '<http://docutils.sourceforge.net/docs/user/latex.html> for '
24
+ 'the full reference.')
25
+
26
+ publish_cmdline(writer_name='latex', description=description)
venv/bin/rst2man.py ADDED
@@ -0,0 +1,26 @@
1
+ #!/Users/wan/CodeProjects/xbot.plugins.ssh/venv/bin/python3.6
2
+
3
+ # Author:
4
+ # Contact: grubert@users.sf.net
5
+ # Copyright: This module has been placed in the public domain.
6
+
7
+ """
8
+ man.py
9
+ ======
10
+
11
+ This module provides a simple command line interface that uses the
12
+ man page writer to output from ReStructuredText source.
13
+ """
14
+
15
+ import locale
16
+ try:
17
+ locale.setlocale(locale.LC_ALL, '')
18
+ except:
19
+ pass
20
+
21
+ from docutils.core import publish_cmdline, default_description
22
+ from docutils.writers import manpage
23
+
24
+ description = ("Generates plain unix manual documents. " + default_description)
25
+
26
+ publish_cmdline(writer=manpage.Writer(), description=description)