Coverage for adhoc-cicd-odoo-odoo / odoo / tools / osutil.py: 16%
44 statements
« prev ^ index » next coverage.py v7.13.4, created at 2026-03-09 18:15 +0000
« prev ^ index » next coverage.py v7.13.4, created at 2026-03-09 18:15 +0000
1# -*- coding: utf-8 -*-
2# Part of Odoo. See LICENSE file for full copyright and licensing details.
4"""
5Some functions related to the os and os.path module
6"""
7import os
8import re
9import zipfile
12WINDOWS_RESERVED = re.compile(r'''
13 ^
14 # forbidden stems: reserved keywords
15 (:?CON|PRN|AUX|NUL|COM[1-9]|LPT[1-9])
16 # even with an extension this is recommended against
17 (:?\..*)?
18 $
19''', flags=re.IGNORECASE | re.VERBOSE)
20def clean_filename(name, replacement=''):
21 """ Strips or replaces possibly problematic or annoying characters our of
22 the input string, in order to make it a valid filename in most operating
23 systems (including dropping reserved Windows filenames).
25 If this results in an empty string, results in "Untitled" (localized).
27 Allows:
29 * any alphanumeric character (unicode)
30 * underscore (_) as that's innocuous
31 * dot (.) except in leading position to avoid creating dotfiles
32 * dash (-) except in leading position to avoid annoyance / confusion with
33 command options
34 * brackets ([ and ]), while they correspond to shell *character class*
35 they're a common way to mark / tag files especially on windows
36 * parenthesis ("(" and ")"), a more natural though less common version of
37 the former
38 * space (" ")
40 :param str name: file name to clean up
41 :param str replacement:
42 replacement string to use for sequences of problematic input, by default
43 an empty string to remove them entirely, each contiguous sequence of
44 problems is replaced by a single replacement
45 :rtype: str
46 """
47 if WINDOWS_RESERVED.match(name):
48 return "Untitled"
49 return re.sub(r'[^\w_.()\[\] -]+', replacement, name).lstrip('.-') or "Untitled"
51def zip_dir(path, stream, include_dir=True, fnct_sort=None): # TODO add ignore list
52 """
53 : param fnct_sort : Function to be passed to "key" parameter of built-in
54 python sorted() to provide flexibility of sorting files
55 inside ZIP archive according to specific requirements.
56 """
57 path = os.path.normpath(path)
58 len_prefix = len(os.path.dirname(path)) if include_dir else len(path)
59 if len_prefix:
60 len_prefix += 1
62 dir_root_path = os.path.realpath(path)
63 with zipfile.ZipFile(stream, 'w', compression=zipfile.ZIP_DEFLATED, allowZip64=True) as zipf:
64 for dirpath, _dirnames, filenames in os.walk(path):
65 filenames = sorted(filenames, key=fnct_sort)
66 for fname in filenames:
67 bname, ext = os.path.splitext(fname)
68 ext = ext or bname
69 if ext not in ['.pyc', '.pyo', '.swp', '.DS_Store']:
70 fpath = os.path.normpath(os.path.join(dirpath, fname))
71 real_fpath = os.path.realpath(fpath)
72 if os.path.isfile(real_fpath) and os.path.commonpath([dir_root_path, real_fpath]) == dir_root_path:
73 zipf.write(real_fpath, fpath[len_prefix:])
76if os.name != 'nt': 76 ↛ 79line 76 didn't jump to line 79 because the condition on line 76 was always true
77 is_running_as_nt_service = lambda: False
78else:
79 import win32service as ws
80 import win32serviceutil as wsu
82 from contextlib import contextmanager
83 from odoo.release import nt_service_name
85 def is_running_as_nt_service():
86 @contextmanager
87 def close_srv(srv):
88 try:
89 yield srv
90 finally:
91 ws.CloseServiceHandle(srv)
93 try:
94 with close_srv(ws.OpenSCManager(None, None, ws.SC_MANAGER_ALL_ACCESS)) as hscm:
95 with close_srv(wsu.SmartOpenService(hscm, nt_service_name, ws.SERVICE_ALL_ACCESS)) as hs:
96 info = ws.QueryServiceStatusEx(hs)
97 return info['ProcessId'] == os.getppid()
98 except Exception:
99 return False