1# -*- coding: utf-8 -*- 2# Part of Odoo. See LICENSE file for full copyright and licensing details. 3 4""" 5Some functions related to the os and os.path module 6""" 7from contextlib import contextmanager 8import logging 9import os 10from os.path import join as opj 11import tempfile 12import zipfile 13 14_logger = logging.getLogger(__name__) 15 16 17def listdir(dir, recursive=False): 18 """Allow to recursively get the file listing following symlinks, returns 19 paths relative to the provided `dir` except completely broken if the symlink 20 it follows leaves `dir`... 21 """ 22 if not recursive: 23 _logger.getChild('listdir').warning("Deprecated: just call os.listdir...") 24 dir = os.path.normpath(dir) 25 if not recursive: 26 return os.listdir(dir) 27 28 res = [] 29 for root, _, files in os.walk(dir, followlinks=True): 30 r = os.path.relpath(root, dir) 31 # FIXME: what should happen if root is outside dir? 32 yield from (opj(r, f) for f in files) 33 return res 34 35def walksymlinks(top, topdown=True, onerror=None): 36 _logger.getChild('walksymlinks').warning("Deprecated: use os.walk(followlinks=True) instead") 37 return os.walk(top, topdown=topdown, onerror=onerror, followlinks=True) 38 39@contextmanager 40def tempdir(): 41 _logger.getChild('tempdir').warning("Deprecated: use tempfile.TemporaryDirectory") 42 with tempfile.TemporaryDirectory() as d: 43 yield d 44 45def zip_dir(path, stream, include_dir=True, fnct_sort=None): # TODO add ignore list 46 """ 47 : param fnct_sort : Function to be passed to "key" parameter of built-in 48 python sorted() to provide flexibility of sorting files 49 inside ZIP archive according to specific requirements. 50 """ 51 path = os.path.normpath(path) 52 len_prefix = len(os.path.dirname(path)) if include_dir else len(path) 53 if len_prefix: 54 len_prefix += 1 55 56 with zipfile.ZipFile(stream, 'w', compression=zipfile.ZIP_DEFLATED, allowZip64=True) as zipf: 57 for dirpath, dirnames, filenames in os.walk(path): 58 filenames = sorted(filenames, key=fnct_sort) 59 for fname in filenames: 60 bname, ext = os.path.splitext(fname) 61 ext = ext or bname 62 if ext not in ['.pyc', '.pyo', '.swp', '.DS_Store']: 63 path = os.path.normpath(os.path.join(dirpath, fname)) 64 if os.path.isfile(path): 65 zipf.write(path, path[len_prefix:]) 66 67 68if os.name != 'nt': 69 getppid = os.getppid 70 is_running_as_nt_service = lambda: False 71else: 72 import ctypes 73 import win32service as ws 74 import win32serviceutil as wsu 75 76 # based on http://mail.python.org/pipermail/python-win32/2007-June/006174.html 77 _TH32CS_SNAPPROCESS = 0x00000002 78 class _PROCESSENTRY32(ctypes.Structure): 79 _fields_ = [("dwSize", ctypes.c_ulong), 80 ("cntUsage", ctypes.c_ulong), 81 ("th32ProcessID", ctypes.c_ulong), 82 ("th32DefaultHeapID", ctypes.c_ulong), 83 ("th32ModuleID", ctypes.c_ulong), 84 ("cntThreads", ctypes.c_ulong), 85 ("th32ParentProcessID", ctypes.c_ulong), 86 ("pcPriClassBase", ctypes.c_ulong), 87 ("dwFlags", ctypes.c_ulong), 88 ("szExeFile", ctypes.c_char * 260)] 89 90 def getppid(): 91 CreateToolhelp32Snapshot = ctypes.windll.kernel32.CreateToolhelp32Snapshot 92 Process32First = ctypes.windll.kernel32.Process32First 93 Process32Next = ctypes.windll.kernel32.Process32Next 94 CloseHandle = ctypes.windll.kernel32.CloseHandle 95 hProcessSnap = CreateToolhelp32Snapshot(_TH32CS_SNAPPROCESS, 0) 96 current_pid = os.getpid() 97 try: 98 pe32 = _PROCESSENTRY32() 99 pe32.dwSize = ctypes.sizeof(_PROCESSENTRY32) 100 if not Process32First(hProcessSnap, ctypes.byref(pe32)): 101 raise OSError('Failed getting first process.') 102 while True: 103 if pe32.th32ProcessID == current_pid: 104 return pe32.th32ParentProcessID 105 if not Process32Next(hProcessSnap, ctypes.byref(pe32)): 106 return None 107 finally: 108 CloseHandle(hProcessSnap) 109 110 from contextlib import contextmanager 111 from odoo.release import nt_service_name 112 113 def is_running_as_nt_service(): 114 @contextmanager 115 def close_srv(srv): 116 try: 117 yield srv 118 finally: 119 ws.CloseServiceHandle(srv) 120 121 try: 122 with close_srv(ws.OpenSCManager(None, None, ws.SC_MANAGER_ALL_ACCESS)) as hscm: 123 with close_srv(wsu.SmartOpenService(hscm, nt_service_name, ws.SERVICE_ALL_ACCESS)) as hs: 124 info = ws.QueryServiceStatusEx(hs) 125 return info['ProcessId'] == getppid() 126 except Exception: 127 return False 128 129if __name__ == '__main__': 130 from pprint import pprint as pp 131 pp(listdir('../report', True)) 132