brain_multiprocessing.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. # Copyright (c) 2016, 2018, 2020 Claudiu Popa <pcmanticore@gmail.com>
  2. # Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com>
  3. # Copyright (c) 2020-2021 hippo91 <guillaume.peillex@gmail.com>
  4. # Copyright (c) 2020 David Gilman <davidgilman1@gmail.com>
  5. # Copyright (c) 2021 Pierre Sassoulas <pierre.sassoulas@gmail.com>
  6. # Copyright (c) 2021 Marc Mueller <30130371+cdce8p@users.noreply.github.com>
  7. # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
  8. # For details: https://github.com/PyCQA/astroid/blob/main/LICENSE
  9. from astroid.bases import BoundMethod
  10. from astroid.brain.helpers import register_module_extender
  11. from astroid.builder import parse
  12. from astroid.exceptions import InferenceError
  13. from astroid.manager import AstroidManager
  14. from astroid.nodes.scoped_nodes import FunctionDef
  15. def _multiprocessing_transform():
  16. module = parse(
  17. """
  18. from multiprocessing.managers import SyncManager
  19. def Manager():
  20. return SyncManager()
  21. """
  22. )
  23. # Multiprocessing uses a getattr lookup inside contexts,
  24. # in order to get the attributes they need. Since it's extremely
  25. # dynamic, we use this approach to fake it.
  26. node = parse(
  27. """
  28. from multiprocessing.context import DefaultContext, BaseContext
  29. default = DefaultContext()
  30. base = BaseContext()
  31. """
  32. )
  33. try:
  34. context = next(node["default"].infer())
  35. base = next(node["base"].infer())
  36. except (InferenceError, StopIteration):
  37. return module
  38. for node in (context, base):
  39. for key, value in node.locals.items():
  40. if key.startswith("_"):
  41. continue
  42. value = value[0]
  43. if isinstance(value, FunctionDef):
  44. # We need to rebound this, since otherwise
  45. # it will have an extra argument (self).
  46. value = BoundMethod(value, node)
  47. module[key] = value
  48. return module
  49. def _multiprocessing_managers_transform():
  50. return parse(
  51. """
  52. import array
  53. import threading
  54. import multiprocessing.pool as pool
  55. import queue
  56. class Namespace(object):
  57. pass
  58. class Value(object):
  59. def __init__(self, typecode, value, lock=True):
  60. self._typecode = typecode
  61. self._value = value
  62. def get(self):
  63. return self._value
  64. def set(self, value):
  65. self._value = value
  66. def __repr__(self):
  67. return '%s(%r, %r)'%(type(self).__name__, self._typecode, self._value)
  68. value = property(get, set)
  69. def Array(typecode, sequence, lock=True):
  70. return array.array(typecode, sequence)
  71. class SyncManager(object):
  72. Queue = JoinableQueue = queue.Queue
  73. Event = threading.Event
  74. RLock = threading.RLock
  75. BoundedSemaphore = threading.BoundedSemaphore
  76. Condition = threading.Condition
  77. Barrier = threading.Barrier
  78. Pool = pool.Pool
  79. list = list
  80. dict = dict
  81. Value = Value
  82. Array = Array
  83. Namespace = Namespace
  84. __enter__ = lambda self: self
  85. __exit__ = lambda *args: args
  86. def start(self, initializer=None, initargs=None):
  87. pass
  88. def shutdown(self):
  89. pass
  90. """
  91. )
  92. register_module_extender(
  93. AstroidManager(), "multiprocessing.managers", _multiprocessing_managers_transform
  94. )
  95. register_module_extender(
  96. AstroidManager(), "multiprocessing", _multiprocessing_transform
  97. )