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.
venv/bin/rst2odt.py ADDED
@@ -0,0 +1,30 @@
1
+ #!/Users/wan/CodeProjects/xbot.plugins.ssh/venv/bin/python3.6
2
+
3
+ # $Id: rst2odt.py 5839 2009-01-07 19:09:28Z dkuhlman $
4
+ # Author: Dave Kuhlman <dkuhlman@rexx.com>
5
+ # Copyright: This module has been placed in the public domain.
6
+
7
+ """
8
+ A front end to the Docutils Publisher, producing OpenOffice documents.
9
+ """
10
+
11
+ import sys
12
+ try:
13
+ import locale
14
+ locale.setlocale(locale.LC_ALL, '')
15
+ except:
16
+ pass
17
+
18
+ from docutils.core import publish_cmdline_to_binary, default_description
19
+ from docutils.writers.odf_odt import Writer, Reader
20
+
21
+
22
+ description = ('Generates OpenDocument/OpenOffice/ODF documents from '
23
+ 'standalone reStructuredText sources. ' + default_description)
24
+
25
+
26
+ writer = Writer()
27
+ reader = Reader()
28
+ output = publish_cmdline_to_binary(reader=reader, writer=writer,
29
+ description=description)
30
+
@@ -0,0 +1,67 @@
1
+ #!/Users/wan/CodeProjects/xbot.plugins.ssh/venv/bin/python3.6
2
+
3
+ # $Id: rst2odt_prepstyles.py 8346 2019-08-26 12:11:32Z milde $
4
+ # Author: Dave Kuhlman <dkuhlman@rexx.com>
5
+ # Copyright: This module has been placed in the public domain.
6
+
7
+ """
8
+ Fix a word-processor-generated styles.odt for odtwriter use: Drop page size
9
+ specifications from styles.xml in STYLE_FILE.odt.
10
+ """
11
+
12
+ # Author: Michael Schutte <michi@uiae.at>
13
+
14
+ from __future__ import print_function
15
+
16
+ from lxml import etree
17
+ import sys
18
+ import zipfile
19
+ from tempfile import mkstemp
20
+ import shutil
21
+ import os
22
+
23
+ NAMESPACES = {
24
+ "style": "urn:oasis:names:tc:opendocument:xmlns:style:1.0",
25
+ "fo": "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"
26
+ }
27
+
28
+
29
+ def prepstyle(filename):
30
+
31
+ zin = zipfile.ZipFile(filename)
32
+ styles = zin.read("styles.xml")
33
+
34
+ root = etree.fromstring(styles)
35
+ for el in root.xpath("//style:page-layout-properties",
36
+ namespaces=NAMESPACES):
37
+ for attr in el.attrib:
38
+ if attr.startswith("{%s}" % NAMESPACES["fo"]):
39
+ del el.attrib[attr]
40
+
41
+ tempname = mkstemp()
42
+ zout = zipfile.ZipFile(os.fdopen(tempname[0], "w"), "w",
43
+ zipfile.ZIP_DEFLATED)
44
+
45
+ for item in zin.infolist():
46
+ if item.filename == "styles.xml":
47
+ zout.writestr(item, etree.tostring(root))
48
+ else:
49
+ zout.writestr(item, zin.read(item.filename))
50
+
51
+ zout.close()
52
+ zin.close()
53
+ shutil.move(tempname[1], filename)
54
+
55
+
56
+ def main():
57
+ args = sys.argv[1:]
58
+ if len(args) != 1:
59
+ print(__doc__, file=sys.stderr)
60
+ print("Usage: %s STYLE_FILE.odt\n" % sys.argv[0], file=sys.stderr)
61
+ sys.exit(1)
62
+ filename = args[0]
63
+ prepstyle(filename)
64
+
65
+
66
+ if __name__ == '__main__':
67
+ main()
@@ -0,0 +1,23 @@
1
+ #!/Users/wan/CodeProjects/xbot.plugins.ssh/venv/bin/python3.6
2
+
3
+ # $Id: rst2pseudoxml.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 pseudo-XML.
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 pseudo-XML from standalone reStructuredText '
21
+ 'sources (for testing purposes). ' + default_description)
22
+
23
+ publish_cmdline(description=description)
venv/bin/rst2s5.py ADDED
@@ -0,0 +1,24 @@
1
+ #!/Users/wan/CodeProjects/xbot.plugins.ssh/venv/bin/python3.6
2
+
3
+ # $Id: rst2s5.py 4564 2006-05-21 20:44:42Z wiemann $
4
+ # Author: Chris Liechti <cliechti@gmx.net>
5
+ # Copyright: This module has been placed in the public domain.
6
+
7
+ """
8
+ A minimal front end to the Docutils Publisher, producing HTML slides using
9
+ the S5 template system.
10
+ """
11
+
12
+ try:
13
+ import locale
14
+ locale.setlocale(locale.LC_ALL, '')
15
+ except:
16
+ pass
17
+
18
+ from docutils.core import publish_cmdline, default_description
19
+
20
+
21
+ description = ('Generates S5 (X)HTML slideshow documents from standalone '
22
+ 'reStructuredText sources. ' + default_description)
23
+
24
+ publish_cmdline(writer_name='s5', description=description)
venv/bin/rst2xetex.py ADDED
@@ -0,0 +1,27 @@
1
+ #!/Users/wan/CodeProjects/xbot.plugins.ssh/venv/bin/python3.6
2
+
3
+ # $Id: rst2xetex.py 7847 2015-03-17 17:30:47Z milde $
4
+ # Author: Guenter Milde
5
+ # Copyright: This module has been placed in the public domain.
6
+
7
+ """
8
+ A minimal front end to the Docutils Publisher, producing Lua/XeLaTeX code.
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 for compilation with the Unicode-aware TeX variants '
21
+ 'XeLaTeX or LuaLaTeX. '
22
+ 'Reads from <source> (default is stdin) and writes to '
23
+ '<destination> (default is stdout). See '
24
+ '<http://docutils.sourceforge.net/docs/user/latex.html> for '
25
+ 'the full reference.')
26
+
27
+ publish_cmdline(writer_name='xetex', description=description)
venv/bin/rst2xml.py ADDED
@@ -0,0 +1,23 @@
1
+ #!/Users/wan/CodeProjects/xbot.plugins.ssh/venv/bin/python3.6
2
+
3
+ # $Id: rst2xml.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 Docutils XML.
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 Docutils-native XML from standalone '
21
+ 'reStructuredText sources. ' + default_description)
22
+
23
+ publish_cmdline(writer_name='xml', description=description)
@@ -0,0 +1,25 @@
1
+ #!/Users/wan/CodeProjects/xbot.plugins.ssh/venv/bin/python3.6
2
+
3
+ # $Id: rstpep2html.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 from PEP
9
+ (Python Enhancement Proposal) documents.
10
+ """
11
+
12
+ try:
13
+ import locale
14
+ locale.setlocale(locale.LC_ALL, '')
15
+ except:
16
+ pass
17
+
18
+ from docutils.core import publish_cmdline, default_description
19
+
20
+
21
+ description = ('Generates (X)HTML from reStructuredText-format PEP files. '
22
+ + default_description)
23
+
24
+ publish_cmdline(reader_name='pep', writer_name='pep_html',
25
+ description=description)
File without changes
@@ -0,0 +1,19 @@
1
+ # Copyright (c) 2023-2024, zhaowcheng <zhaowcheng@163.com>
2
+
3
+ """
4
+ Exceptions.
5
+ """
6
+
7
+
8
+ class SSHConnectError(Exception):
9
+ """
10
+ SSH connection error.
11
+ """
12
+ pass
13
+
14
+
15
+ class SSHCommandError(Exception):
16
+ """
17
+ SSH command error.
18
+ """
19
+ pass
@@ -0,0 +1,211 @@
1
+ # Copyright (c) 2023-2024, zhaowcheng <zhaowcheng@163.com>
2
+
3
+ """
4
+ SFTP module
5
+ """
6
+
7
+ import os
8
+ import stat
9
+
10
+ from typing import Generator
11
+ from contextlib import contextmanager
12
+
13
+ from paramiko import Transport, SFTPClient, SFTPFile
14
+
15
+ from xbot.framework.logger import getlogger, ExtraAdapter
16
+
17
+
18
+ logger = getlogger(__name__)
19
+
20
+
21
+ class SFTPConnection(object):
22
+ """
23
+ SFTP connection.
24
+ """
25
+ def __init__(self):
26
+ self._sftpclient = None
27
+ self._logger = ExtraAdapter(logger, {})
28
+
29
+ def connect(
30
+ self,
31
+ host: str,
32
+ user: str,
33
+ password: str,
34
+ port: int = 22
35
+ ) -> None:
36
+ """
37
+ Open the connection.
38
+ """
39
+ if self._sftpclient and self._sftpclient.sock.active:
40
+ return
41
+ self._logger.extra['prefix'] = f'sftp://{user}@{host}:{port}'
42
+ self._logger.info('Connecting...')
43
+ t = Transport((host, port))
44
+ t.connect(username=user, password=password)
45
+ self._sftpclient = SFTPClient.from_transport(t)
46
+
47
+ def disconnect(self) -> None:
48
+ """
49
+ Close the connection.
50
+ """
51
+ self._sftpclient.close()
52
+
53
+ def getfile(self, rfile: str, ldir: str, filename: str = None) -> None:
54
+ """
55
+ Get `rfile` from SFTP server into `ldir`.
56
+
57
+ :param rfile: remote file.
58
+ :param ldir: local dir.
59
+ :param filename: specify when you want to rename.
60
+
61
+ >>> getfile('/tmp/myfile', '/home') # /home/myfile
62
+ >>> getfile('/tmp/myfile', 'D:\\') # D:\\myfile
63
+ >>> getfile('/tmp/myfile', '/home', 'newfile') # /home/newfile
64
+ """
65
+ ldir = os.path.join(ldir, '')
66
+ filename = filename or self.basename(rfile)
67
+ lfile = os.path.join(ldir, filename)
68
+ self._logger.info(f'Getting file {lfile} <= {rfile}')
69
+ self._sftpclient.get(rfile, lfile)
70
+
71
+ def putfile(self, lfile: str, rdir: str, filename: str = None) -> None:
72
+ """
73
+ Put `lfile` into the `rdir` of SFTP server.
74
+
75
+ :param lfile: local file.
76
+ :param rdir: remote dir.
77
+ :param filename: specify when you want to rename.
78
+
79
+ >>> putfile('/home/myfile', '/tmp') # /tmp/myfile
80
+ >>> putfile('D:\\myfile', '/tmp') # /tmp/myfile
81
+ >>> putfile('/home/myfile', '/tmp', 'newfile') # /tmp/newfile
82
+ """
83
+ rdir = self.join(rdir, '')
84
+ filename = filename or os.path.basename(lfile)
85
+ rfile = self.join(rdir, filename)
86
+ self._logger.info(f'Putting file {lfile} => {rfile}')
87
+ self._sftpclient.put(lfile, rfile)
88
+
89
+ def getdir(self, rdir: str, ldir: str) -> None:
90
+ """
91
+ Get `rdir` from SFTP server into `ldir`.
92
+
93
+ :param rdir: remote dir.
94
+ :param ldir: local dir.
95
+
96
+ >>> getdir('/tmp/mydir', '/home') # /home/mydir
97
+ >>> getdir('/tmp/mydir', 'D:\\') # D:\\mydir
98
+ """
99
+ rdir = self.normpath(rdir)
100
+ ldir = os.path.join(ldir, '')
101
+ self._logger.info(f'Getting dir {ldir} <= {rdir}')
102
+ for top, dirs, files in self.walk(rdir):
103
+ basename = self.basename(top)
104
+ ldir = os.path.join(ldir, basename)
105
+ if not os.path.exists(ldir):
106
+ os.makedirs(ldir)
107
+ for f in files:
108
+ r = self.join(top, f)
109
+ l = os.path.join(ldir, f)
110
+ self._sftpclient.get(r, l)
111
+ for d in dirs:
112
+ l = os.path.join(ldir, d)
113
+ if not os.path.exists(l):
114
+ os.makedirs(l)
115
+
116
+ def putdir(self, ldir: str, rdir: str) -> None:
117
+ """
118
+ Put `ldir` into the `rdir` of SFTP server.
119
+
120
+ :param ldir: local dir.
121
+ :param rdir: remote dir.
122
+
123
+ >>> putdir('/tmp/mydir', '/home') # /home/mydir
124
+ >>> putdir('D:\\mydir', '/home') # /home/mydir
125
+ """
126
+ ldir = os.path.normpath(ldir)
127
+ rdir = self.join(rdir, '')
128
+ self._logger.info(f'Putting dir {ldir} => {rdir}')
129
+ for top, dirs, files in os.walk(os.path.normpath(ldir)):
130
+ basename = os.path.basename(top)
131
+ rdir = self.join(rdir, basename)
132
+ if not self.exists(rdir):
133
+ self.makedirs(rdir)
134
+ for f in files:
135
+ l = os.path.join(top, f)
136
+ r = self.join(rdir, f)
137
+ self._sftpclient.put(l, r)
138
+ for d in dirs:
139
+ r = self.join(rdir, d)
140
+ if not self.exists(r):
141
+ self.makedirs(r)
142
+
143
+ def join(self, *paths: str) -> str:
144
+ """
145
+ Similar to os.path.join().
146
+ """
147
+ paths = [p.rstrip('/') for p in paths]
148
+ return '/'.join(paths)
149
+
150
+ def normpath(self, path: str) -> str:
151
+ """
152
+ Similar to os.path.normpath().
153
+ """
154
+ segs = [s.strip('/') for s in path.split('/')]
155
+ path = self.join(*segs)
156
+ return path.rstrip('/')
157
+
158
+ def basename(self, path: str) -> str:
159
+ """
160
+ Similar to os.path.basename().
161
+ """
162
+ return path.rsplit('/', 1)[-1]
163
+
164
+ def exists(self, path: str) -> str:
165
+ """
166
+ Similar to os.path.exists().
167
+ """
168
+ try:
169
+ self._sftpclient.stat(path)
170
+ return True
171
+ except FileNotFoundError:
172
+ return False
173
+
174
+ def walk(self, path: str):
175
+ """
176
+ Similar to os.walk().
177
+ """
178
+ dirs, files = [], []
179
+ for a in self._sftpclient.listdir_attr(path):
180
+ if stat.S_ISDIR(a.st_mode):
181
+ dirs.append(a.filename)
182
+ else:
183
+ files.append(a.filename)
184
+ yield path, dirs, files
185
+
186
+ for d in dirs:
187
+ for w in self.walk(self.join(path, d)):
188
+ yield w
189
+
190
+ def makedirs(self, path: str) -> str:
191
+ """
192
+ Similar to os.makedirs().
193
+ """
194
+ self._logger.info('Makedirs %s' % path)
195
+ curpath = '/'
196
+ for p in path.split('/'):
197
+ curpath = self.join(curpath, p)
198
+ if not self.exists(curpath):
199
+ self._sftpclient.mkdir(curpath)
200
+
201
+ @contextmanager
202
+ def open(self, filepath: str, mode: str = 'r') -> Generator[SFTPFile, str, None]:
203
+ """
204
+ Similar to builtin open().
205
+ """
206
+ self._logger.info('Open %s with mode=%s' % (filepath, mode))
207
+ f = self._sftpclient.open(filepath, mode)
208
+ try:
209
+ yield f
210
+ finally:
211
+ f.close()