Source code for gigl.common.utils.os_utils
import importlib
import subprocess
from io import TextIOWrapper
from typing import Optional
from gigl.common.logger import Logger
[docs]
def num_lines_in_file(f: TextIOWrapper) -> int:
f.seek(0) # Reset read pointer
return sum(1 for _ in f)
[docs]
def import_obj(obj_path: str):
"""
Given an object path by name (e.g. "module_a.module_b.object_c"), returns object_c.
Args:
obj_path (str): The object path by name.
Returns:
object: The imported object.
"""
def _import_module(module_or_obj_name: str) -> tuple:
"""
Given an object path by name (e.g. "module_a.module_b.object_c"), returns a handle to module_a.module_b and the object name ("object_c").
Args:
module_or_obj_name (str): The object path by name.
Returns:
tuple: A tuple containing the imported module and the relative object name.
"""
parts = module_or_obj_name.split(".")
for i in range(len(parts), 0, -1):
partial_path = ".".join(parts[:i])
logger.info(f"Will try importing module: {partial_path}")
try:
module = importlib.import_module(partial_path)
relative_obj_name = ".".join(parts[i:])
logger.info(
f"Successfully imported module = {module}, which potentially has object = {relative_obj_name}"
)
return module, relative_obj_name
except ImportError as e:
logger.info(f'Unable to import "{partial_path}".')
logger.info(f"{e}")
raise ImportError(module_or_obj_name)
def _find_obj_in_module(module: object, relative_obj_name: str) -> object:
"""
Given a module (e.g. module_a.module_b) and a relative object name (e.g. "object_c"), return a handle for object_c.
Args:
module (module): The module to search for the object.
relative_obj_name (str): The relative object name.
Returns:
object: The found object.
"""
obj = module
for part in relative_obj_name.split("."):
logger.info(f"Trying to access {part} in {obj}")
try:
obj = getattr(obj, part)
except AttributeError as e:
logger.error(f"Could not find the attribute {part} in {obj}")
try:
module = importlib.import_module(obj_path)
except ImportError as import_error:
logger.error(
f"Could not import module {obj_path} either. Import error: {import_error}"
)
logger.error(e)
raise e
return obj
module, relative_obj_name = _import_module(obj_path)
return _find_obj_in_module(module, relative_obj_name)
[docs]
def run_command_and_stream_stdout(cmd: str) -> Optional[int]:
"""
Executes a command and streams the stdout output.
Args:
cmd (str): The command to be executed.
Returns:
Optional[int]: The return code of the command, or None if the command failed to execute.
"""
process = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
while True:
output = process.stdout.readline() # type: ignore
if output == b"" and process.poll() is not None:
break
if output:
print(output.strip())
return_code: Optional[int] = process.poll()
return return_code