Browse Source

Version 2

new version of pytutils
Josue Gomez 1 year ago
parent
commit
2d12eeffd1
8 changed files with 220 additions and 26 deletions
  1. 4
    0
      .gitignore
  2. 26
    24
      __init__.py
  3. 55
    0
      localenv.py
  4. 16
    0
      oracle.py
  5. 3
    1
      pysyspath2
  6. 3
    1
      pysyspath3
  7. 52
    0
      remote.py
  8. 61
    0
      sendmail.py

+ 4
- 0
.gitignore View File

@@ -1,2 +1,6 @@
1 1
 
2 2
 __pycache__/
3
+
4
+\.idea/
5
+
6
+*.pyc

+ 26
- 24
__init__.py View File

@@ -4,47 +4,49 @@ r"""
4 4
 To use, simply 'import pyutils' 
5 5
 
6 6
 shellExecute can receive a cmd as str or arr example 
7
-    >>> pyutils.shellExecute('date')
7
+    >>> pyutils.shell_execute('date')
8 8
     (b'mi\xc3\xa9 ene 30 11:35:00 CST 2019\n', b'')
9
-    >>> pyutils.shellExecute(['echo',"'hola mundo'"])
9
+    >>> pyutils.shell_execute(['echo',"'hola mundo'"])
10 10
     (b"'hola mundo'\n", b'')
11
+        
11 12
 """
12 13
 
13 14
 __author__ = 'Josue Gomez <jgomez@jesrat.com>'
15
+__maintainer__ = "Josue Gomez"
16
+__email__ = "jgomez@binkfe.com"
17
+__license__ = "GPL"
14 18
 __version__ = '2.0'
15
-__all__ = [ 'resizeTTY', 'shellExecute', 'progressBar', 'getSensible', ]
16
-__status__  = "production"
17
-__date__    = "30 January 2019"
19
+__all__ = ['', ]
20
+__status__ = "production"
21
+__date__ = "30 January 2019"
18 22
 
19
-import os, sys, subprocess
20
-from dotenv import load_dotenv 
21 23
 
24
+import sys
25
+import subprocess
22 26
 
23
-result = os.environ.get('MYENV')
24
-load_dotenv(result)
25
-
26
-def getSensible(key):
27
-    return os.environ.get(key)
28 27
 
29 28
 def pysyspath():
30 29
     print(sys.version)
31 30
     for pth in sys.path:
32 31
         print(pth)
33 32
 
34
-def resizeTTY(rows, cols):
33
+
34
+def resize_tty(rows, cols):
35 35
     sys.stdout.write("\x1b[8;{rows};{cols}t".format(rows=rows, cols=cols))
36 36
 
37
-def shellExecute(cmd,stdin=None):
38
-    rpt = subprocess.Popen(cmd, stdin=stdin, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
39
-    stdout, stderr = rpt.communicate()
40
-    return stdout, stderr
41 37
 
42
-def progressBar(progress, total, status=''):
43
-    ttySize = shellExecute(['stty','size'])
44
-    ttySize = ttySize[0].decode().split(' ')
45
-    barLen = round(int(ttySize[1])/100*90)
46
-    fillLen = int(round(barLen * progress / float(total)))
38
+def shell_execute(cmd, stdin=None):
39
+    proc = subprocess.Popen(cmd, stdin=stdin, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
40
+    stdout, stderr = proc.communicate()
41
+    return stdout, stderr, proc.returncode
42
+
43
+
44
+def progress_bar(progress, total, status=''):
45
+    ttysize = shell_execute(['stty','size'])
46
+    ttysize = ttysize[0].decode().split(' ')
47
+    barlen = round(int(ttysize[1])/100*90)
48
+    fill_len = int(round(barlen * progress / float(total)))
47 49
     percent = round(100.0 * progress / float(total), 1)
48
-    bar = '■' * fillLen + '-' * (barLen - fillLen)
50
+    bar = '■' * fill_len + '-' * (barlen - fill_len)
49 51
     sys.stdout.write('[%s] %s%s ...%s\r' % (bar, percent, '%', status))
50
-    sys.stdout.flush()
52
+    sys.stdout.flush()

+ 55
- 0
localenv.py View File

@@ -0,0 +1,55 @@
1
+import os
2
+import sys
3
+
4
+
5
+class NoEnvironmentFile(Exception):
6
+    pass
7
+
8
+
9
+class LocalEnv:
10
+    def __init__(self):
11
+        self.file = None
12
+        self.data = {}
13
+
14
+    def load(self, file=None):
15
+        """
16
+        If no file is defined, the .env file will be searched
17
+        in invoker module's directory
18
+        """
19
+        if file is not None:
20
+            self.file = file
21
+        else:
22
+            self.file = self._invoker()
23
+
24
+        if not os.path.isfile(self.file):
25
+            raise NoEnvironmentFile(f'for file {self.file}')
26
+
27
+        with open(self.file) as f:
28
+            for line in f:
29
+                line = line.strip()
30
+                if not line or line.startswith('#') or '=' not in line:
31
+                    continue
32
+                key, value = line.split('=', 1)
33
+                key = key.replace('export', '')
34
+                key = key.strip()
35
+                value = value.strip().strip('\'"')
36
+                self.data[key] = value
37
+
38
+    def get(self, key, cast=None):
39
+        if cast is None:
40
+            return self.data[key]
41
+
42
+        return cast(self.data[key])
43
+
44
+    @staticmethod
45
+    def _invoker():
46
+        # tip from:
47
+        # https://github.com/henriquebastos/python-decouple/blob/master/decouple.py
48
+        # MAGIC! Get the caller's module path.
49
+        frame = sys._getframe()
50
+        path = os.path.dirname(frame.f_back.f_back.f_code.co_filename)
51
+        file = os.path.join(path, '.env')
52
+        return file
53
+
54
+
55
+localenv = LocalEnv()

+ 16
- 0
oracle.py View File

@@ -0,0 +1,16 @@
1
+import cx_Oracle
2
+
3
+
4
+class OraConn:
5
+    def __init__(self, str_conn, conn_name=None):
6
+        self.conn = cx_Oracle.connect(str_conn, encoding='UTF-8')
7
+        self.cur = self.conn.cursor()
8
+        if conn_name is not None:
9
+            self.cur.callproc('DBMS_APPLICATION_INFO.SET_MODULE', [conn_name, None])
10
+        self.cur.close()
11
+
12
+    def __enter__(self):
13
+        return self.conn
14
+
15
+    def __exit__(self, exc_type, exc_val, exc_tb):
16
+        self.conn.close()

+ 3
- 1
pysyspath2 View File

@@ -1,8 +1,10 @@
1 1
 #!/usr/bin/env python2
2 2
 import pyutils as utl
3 3
 
4
+
4 5
 def main():
5 6
 	utl.pysyspath()
6 7
 
8
+
7 9
 if __name__ == "__main__":
8
-	main()
10
+	main()

+ 3
- 1
pysyspath3 View File

@@ -1,8 +1,10 @@
1 1
 #!/usr/bin/env python3
2 2
 import pyutils as utl
3 3
 
4
+
4 5
 def main():
5 6
 	utl.pysyspath()
6 7
 
8
+
7 9
 if __name__ == "__main__":
8
-	main()
10
+	main()

+ 52
- 0
remote.py View File

@@ -0,0 +1,52 @@
1
+import paramiko
2
+
3
+
4
+class RemoteSSH:
5
+    def __init__(self, auth_info):
6
+        if not isinstance(auth_info, tuple) or len(auth_info) != 4:
7
+            raise AssertionError(f'expected tuple (host, port, user, password) instead got {auth_info}')
8
+
9
+        self.host = auth_info[0]
10
+        self.port = auth_info[1]
11
+        self.user = auth_info[2]
12
+        self.pssw = auth_info[3]
13
+        self.sock = paramiko.Transport((self.host, self.port))
14
+        self.sock.connect(username=self.user, password=self.pssw)
15
+
16
+    def __exit__(self, exc_type, exc_val, exc_tb):
17
+        self.sock.close()
18
+
19
+
20
+class RemoteExecute(RemoteSSH):
21
+    def __init__(self, auth_info):
22
+        super().__init__(auth_info)
23
+        self.session = self.sock.open_channel(kind='session')
24
+
25
+    def __enter__(self):
26
+        return self
27
+
28
+    def __exit__(self, exc_type, exc_val, exc_tb):
29
+        self.session.close()
30
+        super().__exit__(exc_type, exc_val, exc_tb)
31
+
32
+    def execute(self, command):
33
+        stdout = b''
34
+        self.session.exec_command(command)
35
+        while True:
36
+            stdout += self.session.recv(4096)
37
+            if self.session.exit_status_ready():
38
+                break
39
+        return stdout
40
+
41
+
42
+class Sftp(RemoteSSH):
43
+    def __init__(self, auth_info):
44
+        super().__init__(auth_info)
45
+        self.sftp = paramiko.SFTPClient.from_transport(self.sock)
46
+
47
+    def __enter__(self):
48
+        return self.sftp
49
+
50
+    def __exit__(self, exc_type, exc_val, exc_tb):
51
+        self.sftp.close()
52
+        super().__exit__(exc_type, exc_val, exc_tb)

+ 61
- 0
sendmail.py View File

@@ -0,0 +1,61 @@
1
+import smtplib
2
+from os.path import basename
3
+from email.mime.text import MIMEText
4
+from email.utils import COMMASPACE
5
+from email.mime.multipart import MIMEMultipart
6
+from email.mime.application import MIMEApplication
7
+
8
+
9
+class SendMail:
10
+    def __init__(self, auth_info):
11
+        if not isinstance(auth_info, tuple) or len(auth_info) != 4:
12
+            raise AssertionError(f'expected tuple (host, port, user, password) instead got {auth_info}')
13
+
14
+        self.host = auth_info[0]
15
+        self.port = auth_info[1]
16
+        self.user = auth_info[2]
17
+        self.pssw = auth_info[3]
18
+        self.conn = None
19
+        self.msg = None
20
+
21
+    def __enter__(self):
22
+        self.open_conn()
23
+        return self
24
+
25
+    def __exit__(self, exc_type, exc_val, exc_tb):
26
+        self.conn.close()
27
+
28
+    def open_conn(self):
29
+        if int(self.port) == 465:
30
+            self.conn = smtplib.SMTP_SSL(self.host, 465)
31
+        else:
32
+            self.conn = smtplib.SMTP(self.host, self.port)
33
+            self.conn.starttls()
34
+        self.conn.login(self.user, self.pssw)
35
+
36
+    def content(self, fromaddr, toaddr, subject, msg):
37
+        if not isinstance(toaddr, list):
38
+            raise AssertionError('destination address should be a list []')
39
+        self.msg = MIMEMultipart()
40
+        self.msg['Subject'] = subject
41
+        self.msg['From'] = fromaddr
42
+        self.msg['To'] = COMMASPACE.join(toaddr)
43
+        self.msg.attach(MIMEText(msg, 'html'))
44
+
45
+    def attach(self, files):
46
+        if not isinstance(files, list):
47
+            raise AssertionError('file(s) to attach should be a list []')
48
+
49
+        for file in files:
50
+            filename = basename(file)
51
+            with open(file, "rb") as f:
52
+                fl = MIMEApplication(f.read(), Name=filename)
53
+            fl['Content-Disposition'] = f'attachment; filename="{filename}"'
54
+            self.msg.attach(fl)
55
+
56
+        print(self.msg)
57
+
58
+    def send(self):
59
+        if self.msg is None:
60
+            raise Exception('msg is not defined')
61
+        self.conn.send_message(self.msg)