kkpyutil 1.48.0__tar.gz → 1.49.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: kkpyutil
3
- Version: 1.48.0
3
+ Version: 1.49.1
4
4
  Summary: Building blocks for sysadmin and DevOps
5
5
  Home-page: https://github.com/kakyoism/kkpyutil/
6
6
  License: MIT
@@ -2084,6 +2084,26 @@ def sync_dirs(src_root, dst_root, logger=glogger, sudo=False):
2084
2084
  - assume src and dst folders are the same level of folder tree
2085
2085
  - the result will be dst_root mirrors src_root
2086
2086
  """
2087
+ def _run_sudo_command(_cmd, password, _logger):
2088
+ sudo_cmd = ['sudo', '-S'] + _cmd
2089
+ try:
2090
+ process = subprocess.Popen(
2091
+ sudo_cmd,
2092
+ stdin=subprocess.PIPE,
2093
+ stdout=subprocess.PIPE,
2094
+ stderr=subprocess.PIPE,
2095
+ text=True
2096
+ )
2097
+ stdout, stderr = process.communicate(input=f'{password}\n')
2098
+ if process.returncode == 0:
2099
+ _logger.debug(f"Successfully executed: {' '.join(_cmd)}")
2100
+ return True
2101
+ else:
2102
+ _logger.error(f"Sudo command failed: {stderr}")
2103
+ return False
2104
+ except Exception as e:
2105
+ _logger.error(f"Failed to execute sudo command: {e}")
2106
+ return False
2087
2107
  # Ensure the source directory exists
2088
2108
  if not os.path.exists(src_root):
2089
2109
  logger.error(f"Error: Source directory {src_root} does not exist.")
@@ -2110,21 +2130,23 @@ def sync_dirs(src_root, dst_root, logger=glogger, sudo=False):
2110
2130
  if not user:
2111
2131
  logger.error("Could not determine the current user.")
2112
2132
  return False
2113
- try:
2114
- # rsync flags:
2115
- # -a: Archive mode (preserves links, etc.)
2116
- # --chown: Forces the owner:group of all copied files
2117
- # Note: 'staff' is the default group for users on macOS
2118
- cmd = [
2119
- "sudo", "rsync", "-av", "--inplace",
2120
- f"--chown={user}:staff",
2121
- osp.join(src_root, ""), # Trailing slash copies contents
2122
- dst_root
2123
- ]
2124
- logger.info(f"Syncing to {dst_root} and setting owner to '{user}'...")
2125
- subprocess.check_call(cmd)
2126
- except subprocess.CalledProcessError as e:
2127
- logger.error(f"Sync failed with error code: {e.returncode}")
2133
+ pwd = prompt_macos_admin_password()
2134
+ if pwd is None:
2135
+ logger.error('Failed to get admin password')
2136
+ return False
2137
+ # rsync flags:
2138
+ # -a: Archive mode (preserves links, etc.)
2139
+ # --chown: Forces the owner:group of all copied files
2140
+ # Note: 'staff' is the default group for users on macOS
2141
+ cmd = [
2142
+ 'rsync', '-av', '--inplace',
2143
+ f'--chown={user}:staff',
2144
+ osp.join(src_root, ''), # Trailing slash copies contents
2145
+ dst_root
2146
+ ]
2147
+ logger.info(f"Syncing to {dst_root} and setting owner to '{user}'...")
2148
+ if not _run_sudo_command(cmd, pwd, logger):
2149
+ logger.error(f'Sync failed with command: {cmd}; you may have entered wrong password')
2128
2150
  return False
2129
2151
  return True
2130
2152
 
@@ -3188,12 +3210,33 @@ def json_from_text(json_str):
3188
3210
  except json.JSONDecodeError as e:
3189
3211
  return None, e
3190
3212
 
3213
+
3214
+ def prompt_macos_admin_password(action="Your operation"):
3215
+ # Use {{ }} to escape curly braces in an f-string for AppleScript lists
3216
+ applescript = f'''
3217
+ display dialog "{action} requires administrator privileges. Please enter your password:" default answer "" with hidden answer buttons {{"Cancel", "OK"}} default button "OK"
3218
+ text returned of the result
3219
+ '''
3220
+ try:
3221
+ # We add 'with echoing' logic or focus if needed,
3222
+ # but the main fix is the braces below.
3223
+ result = subprocess.run(
3224
+ ['osascript', '-e', applescript],
3225
+ capture_output=True,
3226
+ text=True,
3227
+ check=True
3228
+ )
3229
+ return result.stdout.strip()
3230
+ except subprocess.CalledProcessError as e:
3231
+ # If the dialog doesn't show, check e.stderr for AppleScript errors
3232
+ return None
3233
+
3234
+
3191
3235
  # endregion
3192
3236
 
3193
3237
 
3194
3238
  def _test():
3195
- # print(say('hello'))
3196
- print(create_guid())
3239
+ sync_dirs('/Volumes/public/Audio/Tools/WwisePlugins/MiaSidechainRecv/2025.2.3.1/Wwise2023.1/Authoring', '/Library/Application Support/Audiokinetic/Wwise 2023.1.14.8770/Authoring', sudo=True)
3197
3240
 
3198
3241
 
3199
3242
  if __name__ == '__main__':
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "kkpyutil"
3
- version = "1.48.0"
3
+ version = "1.49.1"
4
4
  description = "Building blocks for sysadmin and DevOps"
5
5
  authors = ["Beinan Li <li.beinan@gmail.com>"]
6
6
  maintainers = ["Beinan Li <li.beinan@gmail.com>"]
File without changes
File without changes