Overview

module url https://pypi.org/project/pyosal.html
git repository https://bitbucket.org/arrizza-public/pyosal
git command git clone git@bitbucket.org:arrizza-public/pyosal.git
verification report https://arrizza.com/web-ver/pyosal-report.html
version info
OS Language #Runs Last Run Cov%
macOS 15.6 Python 3.12 39 2026-07-14 15%
macOS 26.6 Python 3.12 16 2026-08-02 0%
win32 Windows 11 Python 3.12 52 2026-08-03 15%
Ubuntu 24.04 noble Python 3.12 131 2026-08-03 19%

Summary

pyosal is an Operating System Abstraction Layer written in Python. It contains various functions help write cross-platform python code.

see doc/pyosal_api.md or the website above for more information about these functions.

Over time, I will be searching through my projects looking for code like:

if  pyosal.os_name == 'ubuntu':
    do_some_thing_ubu()
elif  pyosal.os_name == 'msys2':
    do_some_thing_msys2()

It might be possible that do_some_thing() is a viable OSAL function to be added to pyosal.

Function Summary

A summary of the functions available are:

Name Type Description
os_name property get OS name/tag
os_version property get OS version info
python_version property get python version info
root_dir property get path for root directory
root_dir_msys2 property get root directory for msys2 shells
userid property get current userid
hostname property get current PC's hostname
os_valid property get list of recognized valid OS names
curr_repo_dir property current repo directory converted to posix
curr_repo_name property current repo name
run_cmd_timeout function run a command in a subprocess, terminate after a timeout
run_cmd function run a command in a subprocess
stdout_flush function flush for stdout
stderr_flush function flush for stderr
xlat_to_win function convert a path to windows i.e. backslashes
xlat_to_posix function convert a path to posix i.e. forward slashes
xlat_dir_to_relative function convert a path to relative to home
abort function abort the current script

pyosal API

This is a summary of the functions available for pyosal.

see sample/app.py for sample code.

📁 various OS values

🛠️ os_name (property)

  • Desc: get OS name/tag
  • Returns: os_name
  • Sample code:
    if pyosal.os_name in ['ubuntu', 'macos']:
        svc.log.info(f'posix os: {pyosal.os_name}')
    elif pyosal.os_name in ['msys2']:
        svc.log.info(f'win os  : {pyosal.os_name}')
    else:
        svc.log.info(f'other   : {pyosal.os_name}')
    
  • Output:
    posix os: ubuntu
    

🛠️ os_valid (property)

  • Desc: get list of recognized valid OS names. see os_name
  • Sample code:
    svc.log.info(f'valid: {pyosal.os_valid}')
    
  • Output:
    valid: ['ubuntu', 'macos', 'msys2', 'psi', 'rpi']
    

🛠️ os_version (property)

  • Desc: get OS version info
  • Returns: os_version
  • Sample code:
    svc.log.info(f'os_version: {pyosal.os_version}')
    
  • Output:
    os_version: Ubuntu 24.04 noble
    

🛠️ python_version (property)

  • Desc: get python version
  • Returns: python_version
  • Sample code:
    svc.log.info(f'python_version: {pyosal.python_version}')
    
  • Output:
    python_version: Python 3.12
    

🛠️ userid (property)

  • Desc: get current userid
  • Sample code:
    svc.log.info(f'userid    : {pyosal.userid}')
    
  • Output:
    userid    : your-userid
    
  • Returns: userid

🛠️ hostname (property)

  • Desc: get current PC's hostname
  • Returns: hostname
  • Sample code:
    svc.log.info(f'hostname  : {pyosal.hostname}')
    
  • Output:
    hostname  : your-hostname
    

📁 various paths and repo info

🛠️ curr_repo_dir (property)

  • Desc: get current repo directory converted to posix
  • Returns: the repo dir path
  • Sample code:
    svc.log.info(f'curr_repo_dir : {pyosal.curr_repo_dir}')
    
  • Output:
    curr_repo_dir : /home/your-userid/projects/web/py-mods/pyosal
    

🛠️ curr_repo_name (property)

  • Desc: get current repo name
  • Returns: the repo name
  • Sample code:
    svc.log.info(f'curr_repo_name: {pyosal.curr_repo_name}')
    
  • Output:
    curr_repo_name: pyosal
    

🛠️ root_dir (property)

  • Desc: get path for root directory
  • Returns: root_dir
  • Sample code:
    svc.log.info(f'root_dir : {pyosal.root_dir}')
    
  • Output:
    root_dir : ~                     # on ubuntu
    root_dir : C:/Users/your-userid  # on MSYS2
    root_dir : ~                     # on macos
    

🛠️ root_dir_msys2 (property)

  • Desc: get root directory for msys2 shells
  • Returns: root_dir_msys2
  • Sample code:
    svc.log.info(f'root_dir_msys2: {pyosal.root_dir_msys2}')
    
  • Output:
    root_dir_msys2: ~                     # on ubuntu
    root_dir_msys2: /c/Users/your-userid  # on MSYS2 (note path is posix)
    root_dir_msys2: ~                     # on macos
    

📁 command runner functions

🛠️ run_cmd_timeout

  • Desc: run a command in a subprocess with a timeout
  • Arguments:
    • timeout: (integer) max time to run cmd before terminating/killing the process
    • cmd: the command to run
    • working_dir: the working directory to run the command in; default is '.'
    • use_raw_log: no prefix on line
    • log_file: the log_file to write the lines to
    • print_cb: callback function used to print output; default is None
    • env: the environment variables to use
    • quiet: if True, do not write to stdout
    • msys_tag: used only for MSYS2 processes; matches command line content for PID to kill
  • Returns: rc - return code
  • Sample code:
    timeout = 3  # seconds
    msys_tag = None
    if pyosal.os_name == 'ubuntu':
        cmd = ['gedit', 'out/abc.txt']
    elif pyosal.os_name == 'msys2':
        cmd = ['notepad']
        msys_tag = 'notepad.exe'
    elif pyosal.os_name == 'macos':
        cmd = ['open', '-a', 'TextEdit']
    rc = pyosal.run_cmd_timeout(timeout, cmd, msys_tag=msys_tag)
    svc.log.info(f'run_cmd_timeout rc={rc}')
    
  • Output:
    # on ubuntu: displays GUI app (e.g. gedit) for 3s, then automatically closes
    run_cmd_timeout: running
    [timeout] exceeded 3s, terminating process...
    [timeout] rc=-15 process terminated gracefully
    [timeout] rc=0   process ended due to timeout
    run_cmd_timeout rc=0
    
    # on MSYS2 : displays GUI app (e.g. notepad) for 3s, then automatically closes
    run_cmd_timeout: running
    [timeout] exceeded 3s, terminating process...
    [timeout] msys2 detected...
    [timeout] rc=0   process terminated gracefully
    [timeout] rc=0   process ended due to timeout
    
    # on macos : displays GUI app (e.g. TextEdit) for 3s, then automat
    run_cmd_timeout: running
    [timeout] exceeded 3s, terminating process...
    [timeout] macos detected...
    [timeout] rc=0   process terminated gracefully
    [timeout] rc=0   process ended due to timeout
    run_cmd_timeout rc=0
    
  • Also see sys-tests/test1.sh and test1-timeout.py for more examples:
    sys-tests/test1.sh normal
    # typical output:
    running normal scenario: app ends before timeout
    -- test1_timer: scenario:normal max_time=2
    -- 00:00.000      elapsed=0.0
    -- 00:00.300      awake
    -- 00:00.300      elapsed=0.3
    -- 00:00.600      awake
    -- 00:00.600      elapsed=0.6
    -- 00:00.900      awake
    -- 00:00.900      elapsed=0.9
    -- 00:01.200      awake
    -- 00:01.200      elapsed=1.2
    -- 00:01.501      awake
    -- 00:01.501      elapsed=1.5
    -- 00:01.801      awake
    -- 00:01.801      elapsed=1.8
    -- 00:02.101      awake
    -- 00:02.101      elapsed=2.1
    -- 00:02.101      exiting at: 2.1
    [timeout] rc=0   process finished before timeout
    expected rc=0 act rc=0
    test1: rc=0
    

🛠️ run_cmd

  • Desc: run a command in a subprocess
  • Arguments:
    • cmd: the command to run
    • working_dir: the working directory to run the command in; default is '.'
    • use_raw_log: no prefix on line
    • log_file: the log_file to write the lines to
    • print_cb: callback function used to print output; default is None
    • env: the environment variables to use
    • quiet: if True, do not write to stdout
    • shared_container: used by run_cmd_container to receive the proc value
  • Returns: rc - return code, lines - the output as a list of lines
  • Sample code:
    svc.log.info('run_cmd: running')
    cmd = ['pwd']
    rc, lines = pyosal.run_cmd(cmd)
    svc.log.info(f'run_cmd rc={rc}')
    for lineno, line in enumerate(lines):
        svc.log.info(f'  line {lineno}: {line}')
    
  • Output:
    # on ubuntu
    run_cmd: running
    -- /home/your-userid/projects/web/py-mods/pyosal
    run_cmd rc=0
    
    # on MSYS2
    run_cmd: running
      -- C:/Users/your-userid/projects/web/py-mods/pyosal
    run_cmd rc=0
    
    # on macos
    run_cmd: running
      -- /Users/your-userid/projects/web/py-mods/pyosal
    run_cmd rc=0
    

🛠️ abort

  • Desc: abort the current script. Does a sys.exit(1) so the script will have a return code of 1.
  • Arguments: msg: (optional) message to display
  • Returns: does not return
  • Sample code:
    pyosal.abort('test of abort')
    pyosal.abort()
    
  • Output:
    # note: only one of these lines is output
    ABRT test of abort
    ABRT abort occurred, exiting
    

📁 path translate functions

🛠️ xlat_to_win

  • Desc: convert a windows path to posix i.e. forward slashes
  • Arguments:
    • path: the path to fix
    • force: force the conversion no matter what the OS is
  • Returns: the unfixed path
  • Sample code:
    path = '/c/dir1/dir2'
    svc.log.info(f'xlat_to_win  : {pyosal.xlat_to_win(path)}')
    svc.log.info(f'xlat_to_win  : {pyosal.xlat_to_win(path, force=True)}')
    
  • Output:
    # on ubuntu
    xlat_to_win  : \c\dir1\dir2
    xlat_to_win  : C:\dir1\dir2   # with force
    
    # on MSYS2
    xlat_to_win  : C:\dir1\dir2
    xlat_to_win  : C:\dir1\dir2   # with force
    

🛠️ xlat_to_posix

  • Desc: convert a windows path to posix i.e. forward slashes
  • Arguments:
    • path: the path to fix
    • force: force the conversion no matter what the OS is
  • Returns: the unfixed path
  • Sample code:
    path = 'c:\\dir1\\dir2'
    svc.log.info(f'xlat_to_posix: {pyosal.xlat_to_posix(path)}')
    svc.log.info(f'xlat_to_posix: {pyosal.xlat_to_posix(path, force=True)}')
    
  • Output:
    # on ubuntu 
    xlat_to_posix: c:/dir1/dir2
    xlat_to_posix: /c/dir1/dir2  # with force
    
    # on MSYS2
    xlat_to_posix: /c/dir1/dir2
    xlat_to_posix: /c/dir1/dir2  # with force
    

🛠️ xlat_dir_to_relative

  • Desc: convert a path to relative to home
  • Arguments:
    • path: the path to fix
  • Returns: the relative path
  • Sample code:
    path = '/home/your-userid\\dir1\\dir2'
    svc.log.info(f'xlat_dir_to_relative: {pyosal.xlat_dir_to_relative(path)}')
    path = '/c/Users/your-userid/dir1/dir2'
    svc.log.info(f'xlat_dir_to_relative: {pyosal.xlat_dir_to_relative(path)}')
    
  • Output:
    # on ubuntu, MSYS2
    xlat_dir_to_relative: ~/dir1/dir2
    xlat_dir_to_relative: ~/dir1/dir2
    

📁 misc functions

🛠️ stdout_flush

  • Desc: flush for stdout
  • Arguments:
    • force: (optional) if True, do the buffer flush even if not msys2
  • Sample code:
    pyosal.stdout_flush()
    pyosal.stdout_flush(force=True)
    
  • Output:
    # no output for this command
    

🛠️ stderr_flush

  • Desc: flush for stderr
  • Arguments:
    • force: (optional) if True, do the buffer flush even if not msys2
  • Sample code:
    pyosal.stderr_flush()
    pyosal.stderr_flush(force=True)
    
  • Output:
    # no output for this command
    

📁 UT and Debug functions

🛠️ ut_mode (setter/getter)

  • Desc: set for ut_mode. if set to False (default) then it behaves as per the actual OS. if set to True, then it returns specific values for os_version

Note: this may change as UT needs are met.

  • Arguments:
    • val: new value to use
  • Returns: None
  • Sample code:
    pyosal.ut_mode = False
    svc.log.info(f'ut_mode:{str(pyosal.ut_mode): <5} name:{pyosal.os_name} vers:{pyosal.os_version}')
    pyosal.ut_mode = True
    svc.log.info(f'ut_mode:{str(pyosal.ut_mode): <5} name:{pyosal.os_name} vers:{pyosal.os_version}')  
    
  • Output:
    # on ubuntu: (may change)
    ut_mode:False name:ubuntu vers:Ubuntu 24.04 noble
    ut_mode:True  name:ubuntu vers:ut Ubuntu 24.04 noble
    
    # on msys2: (may change)
    ut_mode:False name:msys2 vers:win32 Windows 11
    ut_mode:True  name:msys2 vers:ut win32 Windows 11
    
    # on macos: (may change)
    ut_mode:False name:macos vers:macOS 26.6
    ut_mode:True  name:macos vers:ut macOS 14.5
    

🛠️ ut_info

  • Desc: set os_name to use
  • Arguments:
    • ut_os_name: new value to use
  • Returns: ut_mode (true/false)
  • Sample code:
    if pyosal.os_name == 'ubuntu':
        ut_os = 'macos'
    elif pyosal.os_name == 'macos':
        ut_os = 'msys2'
    elif pyosal.os_name == 'msys2':
        ut_os = 'ubuntu'
    real_os = pyosal.os_name
    svc.log.info(f'on {real_os}: {pyosal.os_name}')
    pyosal.ut_info(ut_os)
    svc.log.info(f'on {real_os}: {pyosal.os_name}')
    
  • Output:
    # on ubuntu
    on ubuntu before: ubuntu
    on ubuntu after : macos
    
    # on msys2
    on msys2 before: msys2
    on msys2 after : ubuntu
    
    # on macos
    on macos before: macos 
    on macos after : msys2
    

🛠️ set_debug

  • Desc: set debug to print extra info. see run_cmd_timeout() and run_cmd code.
  • Arguments:
    • val: the debug level to use
      • set() : turn off debugging
      • {'timed'} : print()'s for run_cmd_timed
      • {'run'} : print()'s for run_cmd
      • {'run', 'timed'} : for both
  • Returns: None
  • Sample code:
    pyosal.set_debug({'timed'}) # only the run_cmd_timeout debug statements
    pyosal.set_debug({'run'})   # only the run_cmd debug statements
    pyosal.set_debug({'timed', 'run'}) # both sets of debug statements
    pyosal.set_debug(set())      # turn off debugging
    

- John Arrizza