Skip to content

Commit

Permalink
Make some file utils global functions instead of static methods
Browse files Browse the repository at this point in the history
  • Loading branch information
zsoltkebel committed Feb 15, 2024
1 parent 56819d4 commit 1fa809a
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 71 deletions.
125 changes: 61 additions & 64 deletions installation_and_upgrade/ibex_install_utils/file_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,72 +246,69 @@ def dehex_and_decompress(value):
"Argument was type {} with value {}".format(value.__class__.__name__, value)
return zlib.decompress(binascii.unhexlify(value))

@staticmethod
def get_version(path: str):
"""Reads the version of a file from file version info.
def get_version(path: str):
"""Reads the version of a file from file version info.
Args:
path: The path to the file.
Returns:
The string version (x.x.x.x) on successful read, None otherwise.
"""
version = None
try:
info = win32api.GetFileVersionInfo(path, '\\')
ms = info['FileVersionMS']
ls = info['FileVersionLS']
version = f"{win32api.HIWORD(ms)}.{win32api.LOWORD(ms)}.{win32api.HIWORD(ls)}.{win32api.LOWORD(ls)}"
except:
logging.exception(f"Can't get file version info of '{path}'")
logging.info(f"Read version '{version}' from file info of '{path}'")
return version

@staticmethod
def get_msi_property(path: str, property: str) -> str:
"""Reads a property from msi metadata database of a file.
Args:
path: The path to the file.
Returns:
The string version (x.x.x.x) on successful read, None otherwise.
"""
version = None
try:
info = win32api.GetFileVersionInfo(path, '\\')
ms = info['FileVersionMS']
ls = info['FileVersionLS']
version = f"{win32api.HIWORD(ms)}.{win32api.LOWORD(ms)}.{win32api.HIWORD(ls)}.{win32api.LOWORD(ls)}"
except:
logging.exception(f"Can't get file version info of '{path}'")
logging.info(f"Read version '{version}' from file info of '{path}'")
return version

Args:
path: The path to the file.
property: The property to read.
Returns:
The string value of the property on successful read, None otherwise.
"""
value = None
try:
db = msilib.OpenDatabase(path, msilib.MSIDBOPEN_READONLY)
view = db.OpenView("SELECT Value FROM Property WHERE Property='" + property + "'")
view.Execute(None)
result = view.Fetch()
value = result.GetString(1)
except:
logging.exception(f"Can't read property '{property}' from file '{path}'.")
logging.info(f"Read value '{value}' for property '{property}' from file '{path}'.")
return value
def get_msi_property(path: str, property: str) -> str:
"""Reads a property from msi metadata database of a file.
@contextmanager
@staticmethod
def file_in_zip(zipname, peek_at_filename: str):
"""
Usage:
with file_in_zip(zipname, filename_within_zip) as file:
do something
"""
_, file_extension = os.path.splitext(peek_at_filename)
try:
tmp = tempfile.NamedTemporaryFile(mode='wb', suffix=file_extension, delete=False) # Manually delete file.

with zipfile.ZipFile(zipname) as z:
with z.open(peek_at_filename) as zf:
shutil.copyfileobj(zf, tmp)
Args:
path: The path to the file.
property: The property to read.
Returns:
The string value of the property on successful read, None otherwise.
"""
value = None
try:
db = msilib.OpenDatabase(path, msilib.MSIDBOPEN_READONLY)
view = db.OpenView("SELECT Value FROM Property WHERE Property='" + property + "'")
view.Execute(None)
result = view.Fetch()
value = result.GetString(1)
except:
logging.exception(f"Can't read property '{property}' from file '{path}'.")
logging.info(f"Read value '{value}' for property '{property}' from file '{path}'.")
return value

@contextmanager
def file_in_zip(zipname, peek_at_filename: str):
"""
Usage:
with file_in_zip(zipname, filename_within_zip) as file:
do something
"""
_, file_extension = os.path.splitext(peek_at_filename)
try:
tmp = tempfile.NamedTemporaryFile(mode='wb', suffix=file_extension, delete=False) # Manually delete file.

with zipfile.ZipFile(zipname) as z:
with z.open(peek_at_filename) as zf:
shutil.copyfileobj(zf, tmp)

#! Workaround
# Wen trying to read file version you get:
# 'The specified image file did not contain a resource section.'
# unless you close and reopen the file.
tmp.close()
tmp = open(tmp.name)
#! Workaround
# Wen trying to read file version you get:
# 'The specified image file did not contain a resource section.'
# unless you close and reopen the file.
tmp.close()
tmp = open(tmp.name)

yield tmp
finally:
tmp.close()
os.remove(tmp.name) # Manually remove temp file
yield tmp
finally:
tmp.close()
os.remove(tmp.name) # Manually remove temp file
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import re
import subprocess

from ibex_install_utils.file_utils import FileUtils
from ibex_install_utils.file_utils import get_version
from ibex_install_utils.software_dependency import SoftwareDependency
from ibex_install_utils.version_check import VERSION_REGEX, get_major_minor_patch

Expand All @@ -18,4 +18,4 @@ def get_file_pattern(self) -> str:
return r"^Git-([0-9.]*)-[0-9]*-bit.exe"

def get_version_of(self, path: str) -> str:
return FileUtils.get_version(path)
return get_version(path)
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import re
import subprocess

from ibex_install_utils.file_utils import FileUtils
from ibex_install_utils.file_utils import get_msi_property
from ibex_install_utils.software_dependency import SoftwareDependency
from ibex_install_utils.version_check import VERSION_REGEX, get_major_minor_patch

Expand All @@ -18,4 +18,4 @@ def get_file_pattern(self) -> str:
return r"^OpenJDK.*?([0-9.]*)_?[0-9]*.msi"

def get_version_of(self, path: str) -> str:
return FileUtils.get_msi_property(path, "ProductVersion")
return get_msi_property(path, "ProductVersion")
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from ibex_install_utils.software_dependency import SoftwareDependency
from ibex_install_utils.version_check import VERSION_REGEX, get_major_minor_patch
from ibex_install_utils.tasks.common_paths import APPS_BASE_DIR, INST_SHARE_AREA
from ibex_install_utils.file_utils import FileUtils
from ibex_install_utils.file_utils import get_version, file_in_zip

MYSQL8_INSTALL_DIR = os.path.join(APPS_BASE_DIR, "MySQL")

Expand All @@ -26,8 +26,8 @@ def get_version_of(self, path: str) -> str:
filename, _ = os.path.splitext(os.path.basename(path))

exe_within_zip = f'{filename}/bin/mysql.exe'
with FileUtils.file_in_zip(path, exe_within_zip) as mysql_exe:
return FileUtils.get_version(mysql_exe.name)
with file_in_zip(path, exe_within_zip) as mysql_exe:
return get_version(mysql_exe.name)

def get_search_dir(self) -> str:
return os.path.join(INST_SHARE_AREA, "kits$", "CompGroup", "ICP", "MySQL")

0 comments on commit 1fa809a

Please sign in to comment.