Funktionierender Prototyp des Serious Games zur Vermittlung von Wissen zu Software-Engineering-Arbeitsmodellen.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

win32.py 4.7KB

1 year ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. # -*- test-case-name: twisted.python.test.test_win32 -*-
  2. # Copyright (c) Twisted Matrix Laboratories.
  3. # See LICENSE for details.
  4. """
  5. Win32 utilities.
  6. See also twisted.python.shortcut.
  7. @var O_BINARY: the 'binary' mode flag on Windows, or 0 on other platforms, so it
  8. may safely be OR'ed into a mask for os.open.
  9. """
  10. import os
  11. import re
  12. from incremental import Version
  13. from twisted.python.deprecate import deprecatedModuleAttribute
  14. # https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes
  15. ERROR_FILE_NOT_FOUND = 2
  16. ERROR_PATH_NOT_FOUND = 3
  17. ERROR_INVALID_NAME = 123
  18. ERROR_DIRECTORY = 267
  19. O_BINARY = getattr(os, "O_BINARY", 0)
  20. class FakeWindowsError(OSError):
  21. """
  22. Stand-in for sometimes-builtin exception on platforms for which it
  23. is missing.
  24. """
  25. deprecatedModuleAttribute(
  26. Version("Twisted", 21, 2, 0),
  27. "Catch OSError and check presence of 'winerror' attribute.",
  28. "twisted.python.win32",
  29. "FakeWindowsError",
  30. )
  31. try:
  32. WindowsError: OSError = WindowsError
  33. except NameError:
  34. WindowsError = FakeWindowsError
  35. deprecatedModuleAttribute(
  36. Version("Twisted", 21, 2, 0),
  37. "Catch OSError and check presence of 'winerror' attribute.",
  38. "twisted.python.win32",
  39. "WindowsError",
  40. )
  41. _cmdLineQuoteRe = re.compile(r'(\\*)"')
  42. _cmdLineQuoteRe2 = re.compile(r"(\\+)\Z")
  43. def cmdLineQuote(s):
  44. """
  45. Internal method for quoting a single command-line argument.
  46. @param s: an unquoted string that you want to quote so that something that
  47. does cmd.exe-style unquoting will interpret it as a single argument,
  48. even if it contains spaces.
  49. @type s: C{str}
  50. @return: a quoted string.
  51. @rtype: C{str}
  52. """
  53. quote = ((" " in s) or ("\t" in s) or ('"' in s) or s == "") and '"' or ""
  54. return (
  55. quote
  56. + _cmdLineQuoteRe2.sub(r"\1\1", _cmdLineQuoteRe.sub(r'\1\1\\"', s))
  57. + quote
  58. )
  59. def quoteArguments(arguments):
  60. """
  61. Quote an iterable of command-line arguments for passing to CreateProcess or
  62. a similar API. This allows the list passed to C{reactor.spawnProcess} to
  63. match the child process's C{sys.argv} properly.
  64. @param arguments: an iterable of C{str}, each unquoted.
  65. @return: a single string, with the given sequence quoted as necessary.
  66. """
  67. return " ".join([cmdLineQuote(a) for a in arguments])
  68. class _ErrorFormatter:
  69. """
  70. Formatter for Windows error messages.
  71. @ivar winError: A callable which takes one integer error number argument
  72. and returns a L{WindowsError} instance for that error (like
  73. L{ctypes.WinError}).
  74. @ivar formatMessage: A callable which takes one integer error number
  75. argument and returns a C{str} giving the message for that error (like
  76. U{win32api.FormatMessage<http://
  77. timgolden.me.uk/pywin32-docs/win32api__FormatMessage_meth.html>}).
  78. @ivar errorTab: A mapping from integer error numbers to C{str} messages
  79. which correspond to those erorrs (like I{socket.errorTab}).
  80. """
  81. def __init__(self, WinError, FormatMessage, errorTab):
  82. self.winError = WinError
  83. self.formatMessage = FormatMessage
  84. self.errorTab = errorTab
  85. @classmethod
  86. def fromEnvironment(cls):
  87. """
  88. Get as many of the platform-specific error translation objects as
  89. possible and return an instance of C{cls} created with them.
  90. """
  91. try:
  92. from ctypes import WinError
  93. except ImportError:
  94. WinError = None
  95. try:
  96. from win32api import FormatMessage # type: ignore[import]
  97. except ImportError:
  98. FormatMessage = None
  99. try:
  100. from socket import errorTab
  101. except ImportError:
  102. errorTab = None
  103. return cls(WinError, FormatMessage, errorTab)
  104. def formatError(self, errorcode):
  105. """
  106. Returns the string associated with a Windows error message, such as the
  107. ones found in socket.error.
  108. Attempts direct lookup against the win32 API via ctypes and then
  109. pywin32 if available), then in the error table in the socket module,
  110. then finally defaulting to C{os.strerror}.
  111. @param errorcode: the Windows error code
  112. @type errorcode: C{int}
  113. @return: The error message string
  114. @rtype: C{str}
  115. """
  116. if self.winError is not None:
  117. return self.winError(errorcode).strerror
  118. if self.formatMessage is not None:
  119. return self.formatMessage(errorcode)
  120. if self.errorTab is not None:
  121. result = self.errorTab.get(errorcode)
  122. if result is not None:
  123. return result
  124. return os.strerror(errorcode)
  125. formatError = _ErrorFormatter.fromEnvironment().formatError