Files
full_encoach_platform/odoo/odoo/tools/osutil.py
Yamen Ahmad 3e83d8d7d5 feat: add complete EnCoach backend — Odoo 19 + all addons
Includes:
- Odoo 19 framework (odoo/)
- 27 custom EnCoach addons (new_project/custom_addons/)
  - encoach_core, encoach_api, encoach_lms_api, encoach_adaptive_api
  - encoach_exam, encoach_taxonomy, encoach_adaptive, encoach_assignment
  - encoach_ai, encoach_ai_grading, encoach_ai_generation, encoach_ai_media
  - encoach_courseware, encoach_communication, encoach_subscription
  - encoach_notification, encoach_approval, encoach_branding
  - encoach_classroom, encoach_registration, encoach_stats
  - encoach_faq, encoach_ticket, encoach_training, encoach_resources
  - encoach_adaptive_ai, encoach_sis
- 21 OpenEduCat Enterprise modules (new_project/enterprise-19/)
- 14 OpenEduCat Community modules (new_project/openeducat_erp-19.0/)
- Configuration: odoo.conf, requirements.txt, scripts
- 200+ REST API endpoints with JWT authentication
- SRS and test documentation

Made-with: Cursor
2026-04-01 17:10:04 +04:00

100 lines
3.7 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
"""
Some functions related to the os and os.path module
"""
import os
import re
import zipfile
WINDOWS_RESERVED = re.compile(r'''
^
# forbidden stems: reserved keywords
(:?CON|PRN|AUX|NUL|COM[1-9]|LPT[1-9])
# even with an extension this is recommended against
(:?\..*)?
$
''', flags=re.IGNORECASE | re.VERBOSE)
def clean_filename(name, replacement=''):
""" Strips or replaces possibly problematic or annoying characters our of
the input string, in order to make it a valid filename in most operating
systems (including dropping reserved Windows filenames).
If this results in an empty string, results in "Untitled" (localized).
Allows:
* any alphanumeric character (unicode)
* underscore (_) as that's innocuous
* dot (.) except in leading position to avoid creating dotfiles
* dash (-) except in leading position to avoid annoyance / confusion with
command options
* brackets ([ and ]), while they correspond to shell *character class*
they're a common way to mark / tag files especially on windows
* parenthesis ("(" and ")"), a more natural though less common version of
the former
* space (" ")
:param str name: file name to clean up
:param str replacement:
replacement string to use for sequences of problematic input, by default
an empty string to remove them entirely, each contiguous sequence of
problems is replaced by a single replacement
:rtype: str
"""
if WINDOWS_RESERVED.match(name):
return "Untitled"
return re.sub(r'[^\w_.()\[\] -]+', replacement, name).lstrip('.-') or "Untitled"
def zip_dir(path, stream, include_dir=True, fnct_sort=None): # TODO add ignore list
"""
: param fnct_sort : Function to be passed to "key" parameter of built-in
python sorted() to provide flexibility of sorting files
inside ZIP archive according to specific requirements.
"""
path = os.path.normpath(path)
len_prefix = len(os.path.dirname(path)) if include_dir else len(path)
if len_prefix:
len_prefix += 1
dir_root_path = os.path.realpath(path)
with zipfile.ZipFile(stream, 'w', compression=zipfile.ZIP_DEFLATED, allowZip64=True) as zipf:
for dirpath, _dirnames, filenames in os.walk(path):
filenames = sorted(filenames, key=fnct_sort)
for fname in filenames:
bname, ext = os.path.splitext(fname)
ext = ext or bname
if ext not in ['.pyc', '.pyo', '.swp', '.DS_Store']:
fpath = os.path.normpath(os.path.join(dirpath, fname))
real_fpath = os.path.realpath(fpath)
if os.path.isfile(real_fpath) and os.path.commonpath([dir_root_path, real_fpath]) == dir_root_path:
zipf.write(real_fpath, fpath[len_prefix:])
if os.name != 'nt':
is_running_as_nt_service = lambda: False
else:
import win32service as ws
import win32serviceutil as wsu
from contextlib import contextmanager
from odoo.release import nt_service_name
def is_running_as_nt_service():
@contextmanager
def close_srv(srv):
try:
yield srv
finally:
ws.CloseServiceHandle(srv)
try:
with close_srv(ws.OpenSCManager(None, None, ws.SC_MANAGER_ALL_ACCESS)) as hscm:
with close_srv(wsu.SmartOpenService(hscm, nt_service_name, ws.SERVICE_ALL_ACCESS)) as hs:
info = ws.QueryServiceStatusEx(hs)
return info['ProcessId'] == os.getppid()
except Exception:
return False