Fabric: Python3 рдХреЗ рддрд╣рдд рд╕рдорд╛рдирд╛рдВрддрд░ рдирд┐рд╖реНрдкрд╛рджрди

рдХреЛ рдирд┐рд░реНрдорд┐рдд 2 рджрд┐рд╕ре░ 2018  ┬╖  14рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ  ┬╖  рд╕реНрд░реЛрдд: fabric/fabric

рдореИрдВ рдирдП рдХрдкрдбрд╝реЗ рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рд▓рд┐рдП рд╕рдорд╛рдирд╛рдВрддрд░ рдирд┐рд╖реНрдкрд╛рджрди рдкрд░ рдХреЛрдИ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдирд╣реАрдВ рдвреВрдВрдв рдкрд╛ рд░рд╣рд╛ рдерд╛ред рдХреНрдпрд╛ рдпрд╣ рдЕрдЬрдЧрд░ 2 рд╕рдВрд╕реНрдХрд░рдг рдЬреИрд╕рд╛ рд╣реА рд╣реИ, рдпрд╛ рдпрд╣ рдкреНрд░рдЧрддрд┐ рдкрд░ рд╣реИ?

рдзрдиреНрдпрд╡рд╛рдж!

рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА

@akiuni рдЗрд╕рдХреЗ рд▓рд┐рдП рдХреЛрдИ рдкреАрдЖрд░ рд╣реИ? #1912 (рдЯрд┐рдкреНрдкрдгреА)

рдирдорд╕реНрддреЗ, рдореБрдЭреЗ рдРрд╕рд╛ рдирд╣реАрдВ рд▓рдЧрддрд╛.. рд╕рдЪ рдХрд╣реВрдВ, рддреЛ рдореБрдЭреЗ рдкрддрд╛ рд╣реИ рдХрд┐ рдЗрд╕реЗ рдХреИрд╕реЗ рдЬрд╛рдВрдЪрдирд╛ рд╣реИ рдФрд░ рдореБрдЭреЗ рдирд╣реАрдВ рдкрддрд╛ рдХрд┐ рдЗрд╕ рддрд░рд╣ рдХреЗ рд╕рдВрд╢реЛрдзрди рдХреЛ рдЬрдорд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреИрд╕реЗ рдЖрдЧреЗ рдмрдврд╝рдирд╛ рд╣реИ...

рд╕рднреА 14 рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

рд╣рд╛рдВ, рд╣рд╛рд▓рд╛рдВрдХрд┐, рдереНрд░реЗрдбрд┐рдВрдЧ рд╕рдореВрд╣ рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдХрд╛ рд╕рдорд░реНрдерди рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ:

config = Config(overrides={'sudo':{'password': 'changeme'}})

c = ThreadingGroup("[email protected]", "[email protected]", connect_kwargs={"password": "changeme"}, config=config)

c.run("whoami")

c.sudo("whoami") #Throws AttributeError: 'ThreadingGroup' object has no attribute 'sudo'

рдереНрд░реЗрдбрд┐рдВрдЧрдЧреНрд░реБрдк рдиреЗ рдХреЗрд╡рд▓ рд░рди рдХрдорд╛рдВрдб рдХреА рдЕрдиреБрдорддрд┐ рджреА рд╣реИред
https://github.com/fabric/fabric/issues/1899#issue -377714688

рдЖрдк рдХрдорд╛рдВрдб рд╕рдкреЛрд░реНрдЯ рдХреЛ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦ рдФрд░ рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВред

SerialGroup рдФрд░ ThreadingGroup рдореЗрдВ sudo рдХреЛ рд╕рдХреНрд╖рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдкреИрдЪ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЖрдк рдХреНрдпрд╛ рд╕реЛрдЪрддреЗ рд╣реИрдВ?
(рдХрдкрдбрд╝реЗ 2.4 рдкрд░ рд▓рд╛рдЧреВ рдФрд░ рдкрд░реАрдХреНрд╖рдг рдХрд┐рдпрд╛ рдЧрдпрд╛)

--- fabric-orig/group.py    2018-10-30 14:35:22.000000000 +0100
+++ fabric-patched/group.py 2019-02-18 10:16:29.186000000 +0100
@@ -183,12 +183,28 @@
             raise GroupException(results)
         return results

+    def sudo(self, *args, **kwargs):
+        results = GroupResult()
+        excepted = False
+        for cxn in self:
+            try:
+                results[cxn] = cxn.sudo(*args, **kwargs)
+            except Exception as e:
+                results[cxn] = e
+                excepted = True
+        if excepted:
+            raise GroupException(results)
+        return results

 def thread_worker(cxn, queue, args, kwargs):
     result = cxn.run(*args, **kwargs)
     # TODO: namedtuple or attrs object?
     queue.put((cxn, result))

+def thread_worker_sudo(cxn, queue, args, kwargs):
+    result = cxn.sudo(*args, **kwargs)
+    # TODO: namedtuple or attrs object?
+    queue.put((cxn, result))

 class ThreadingGroup(Group):
     """
@@ -208,6 +224,49 @@
             )
             threads.append(thread)
         for thread in threads:
+            thread.start()
+        for thread in threads:
+            # TODO: configurable join timeout
+            # TODO: (in sudo's version) configurability around interactive
+            # prompting resulting in an exception instead, as in v1
+            thread.join()
+        # Get non-exception results from queue
+        while not queue.empty():
+            # TODO: io-sleep? shouldn't matter if all threads are now joined
+            cxn, result = queue.get(block=False)
+            # TODO: outstanding musings about how exactly aggregate results
+            # ought to ideally operate...heterogenous obj like this, multiple
+            # objs, ??
+            results[cxn] = result
+        # Get exceptions from the threads themselves.
+        # TODO: in a non-thread setup, this would differ, e.g.:
+        # - a queue if using multiprocessing
+        # - some other state-passing mechanism if using e.g. coroutines
+        # - ???
+        excepted = False
+        for thread in threads:
+            wrapper = thread.exception()
+            if wrapper is not None:
+                # Outer kwargs is Thread instantiation kwargs, inner is kwargs
+                # passed to thread target/body.
+                cxn = wrapper.kwargs["kwargs"]["cxn"]
+                results[cxn] = wrapper.value
+                excepted = True
+        if excepted:
+            raise GroupException(results)
+        return results
+
+    def sudo(self, *args, **kwargs):
+        results = GroupResult()
+        queue = Queue()
+        threads = []
+        for cxn in self:
+            my_kwargs = dict(cxn=cxn, queue=queue, args=args, kwargs=kwargs)
+            thread = ExceptionHandlingThread(
+                target=thread_worker_sudo, kwargs=my_kwargs
+            )
+            threads.append(thread)
+        for thread in threads:
             thread.start()
         for thread in threads:
             # TODO: configurable join timeout

рдпрд╣ рд╡рд╛рдХрдИ рдХрдорд╛рд▓ рдХрд╛ рд╣реЛрдЧрд╛ @akiuni

рдлреИрдмреНрд░рд┐рдХ2 рдХреЗ рд▓рд┐рдП рдереНрд░реЗрдбрд┐рдВрдЧрдЧреНрд░реБрдк рдореЗрдВ рдПрдХреНрдЬрд╝реАрдХреНрдпреВрдЯ () рдлреАрдЪрд░ рдХреЛ рд╡рд╛рдкрд╕ рд▓рд╛рдирд╛ рдЕрдЪреНрдЫрд╛ рд╣реЛрдЧрд╛ред

@akiuni рдЗрд╕рдХреЗ рд▓рд┐рдП рдХреЛрдИ рдкреАрдЖрд░ рд╣реИ? https://github.com/fabric/fabric/issues/1912#issuecomment -464652728

@akiuni рдЗрд╕рдХреЗ рд▓рд┐рдП рдХреЛрдИ рдкреАрдЖрд░ рд╣реИ? #1912 (рдЯрд┐рдкреНрдкрдгреА)

рдирдорд╕реНрддреЗ, рдореБрдЭреЗ рдРрд╕рд╛ рдирд╣реАрдВ рд▓рдЧрддрд╛.. рд╕рдЪ рдХрд╣реВрдВ, рддреЛ рдореБрдЭреЗ рдкрддрд╛ рд╣реИ рдХрд┐ рдЗрд╕реЗ рдХреИрд╕реЗ рдЬрд╛рдВрдЪрдирд╛ рд╣реИ рдФрд░ рдореБрдЭреЗ рдирд╣реАрдВ рдкрддрд╛ рдХрд┐ рдЗрд╕ рддрд░рд╣ рдХреЗ рд╕рдВрд╢реЛрдзрди рдХреЛ рдЬрдорд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреИрд╕реЗ рдЖрдЧреЗ рдмрдврд╝рдирд╛ рд╣реИ...

рд╣рдореЗрдВ рдЗрд╕реЗ рдЬрд▓реНрдж рд╕реЗ рдЬрд▓реНрдж рдлреИрдмреНрд░рд┐рдХ рдореЗрдВ рдорд┐рд▓рд╛рдирд╛ рд╣реЛрдЧрд╛ред

рдорд┐рдореА рд╡рд░реНрддрдорд╛рди рдХреЛрдб рдХреЛ v 2.5.0 . рдореЗрдВ рджреЗрдЦ рд░рд╣рд╛ рд╣реИ
https://github.com/fabric/fabric/blob/2.5.0/fabric/group.py#L127 рдореИрдВ рджреЗрдЦ рд╕рдХрддрд╛ рд╣реВрдВ рдХрд┐ рдпрд╣ рдХреЛрдб рдЕрдм рдЪрд╛рд▓реВ рдирд╣реАрдВ рд╣реИ, рдФрд░ рд▓реЗрдЦрдХ рдЗрд╕реЗ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд╕рд░реНрд╡реЛрддреНрддрдо рддрд░реАрдХреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реЛрдЪ рд░рд╣реЗ рд╣реИрдВред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдХреЛрдИ рдкреАрдЖрд░ рдирд╣реАрдВ рд╣реЛрдиреЗ рдХреЗ рдХрд╛рд░рдг рдЙрдирдХреЗ рдкрд╛рд╕ рдХреЛрдб рджреНрд╡рд╛рд░рд╛ рдкреЗрд╢ рдХрд┐рдП рдЧрдП рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдкрд░ рдЪрд░реНрдЪрд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреЛрдИ рдордВрдЪ рдирд╣реАрдВ рд╣реИред рдореИрдВ рдЗрд╕реЗ рджреЗрдЦ рд░рд╣рд╛ рд╣реВрдВ, рд▓реЗрдХрд┐рди рдореИрдВ рдПрдХ рд╡рд┐рд╢реЗрд╖рдЬреНрдЮ рдкрд╛рдпрдерди рдХреЛрдбрд░ рдирд╣реАрдВ рд╣реВрдВ, рд▓реЗрдХрд┐рди рдореИрдВ рдЗрд╕реЗ рдкреАрдЖрд░ рдХреЗ рд░реВрдк рдореЗрдВ рдПрдХ рд╢реЙрдЯ рджреЗрдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реВрдВрдЧрд╛

рд╣реИрд▓реЛ, рдореИрдВ git developmentpemen рдХреЗ рд▓рд┐рдП рдЕрднреНрдпрд╕реНрдд рдирд╣реАрдВ рд╣реВрдВ (рдкреАрдЖрд░ рдореЗрд░реЗ рд▓рд┐рдП рдПрдХ рдЕрдЬреАрдм рд╢рдмреНрдж рд╣реИ), рдмреЗрдЭрд┐рдЭрдХ рдореБрдЭреЗ рдмрддрд╛рдПрдВ рдХрд┐ рдХреНрдпрд╛ рдореИрдВ рдорджрдж рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВ

рдЕрд░реЗ @akiuni
рдкреАрдЖрд░ рдкреБрд▓ рдЕрдиреБрд░реЛрдз рдХреЗ рд▓рд┐рдП рдЦрдбрд╝рд╛ рд╣реИ, рдФрд░ рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐, рдпрджрд┐ рдЖрдк рдХреЛрдИ рдмрджрд▓рд╛рд╡ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рдЙрд╕ рдкрд░рд┐рд╡рд░реНрддрди рдХреЛ рдПрдХ рдкреБрд▓ рдЕрдиреБрд░реЛрдз рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕реНрд░реЛрдд рдХреЛрдб рдореЗрдВ рд▓рд╛рддреЗ рд╣реИрдВ, рдЬрд┐рд╕реЗ рддрдм рдмрд╛рддрдЪреАрдд рдХреЗ рд░реВрдк рдореЗрдВ рдорд╛рдирд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдФрд░ рдЗрд╕рдХреА рд╕рдореАрдХреНрд╖рд╛ рд╣реЛрдиреЗ рддрдХ рд╕рдореАрдХреНрд╖рд╛ рдХреА рдЬрд╛ рд╕рдХрддреА рд╣реИред рдЬрдм рдЗрд╕реЗ рд╕реНрд╡реАрдХреГрдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рддреЛ рдкреАрдЖрд░ рджреНрд╡рд╛рд░рд╛ рдкреЗрд╢ рдХрд┐рдП рдЧрдП рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреЛ рдПрдХ рдкреНрд░рддрд┐рдмрджреНрдзрддрд╛ рдХреЗ рд░реВрдк рдореЗрдВ рджреЗрдЦрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдЬреИрд╕реЗ рдореИрдВрдиреЗ рдпрд╣рд╛рдВ рдХрд┐рдпрд╛ рд╣реИ: # 2052
рдкреБрд▓ рдЕрдиреБрд░реЛрдз (рдкреАрдЖрд░) рдореЗрдВ ".рдкреИрдЪ" рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЪрддреБрд░ рдЪрд╛рд▓ рд╣реИ рдЬреИрд╕реЗ рдпрд╣рд╛рдВ: https://patch-diff.githubusercontent.com/raw/fabric/fabric/pull/2052.patch рдЬреЛ рдЖрдкрдХреЛ рдПрдХ рдЕрдВрддрд░ рджреЗрдЧрд╛ рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдореЗрдВ рд╕реЗ (рдЬреИрд╕рд╛ рдХрд┐ рдЖрдкрдиреЗ рдЕрдкрдиреА рдкрд┐рдЫрд▓реА рдЯрд┐рдкреНрдкрдгреА рдореЗрдВ рдЖрдкреВрд░реНрддрд┐ рдХреА рд╣реИ) рд▓реЗрдХрд┐рди рдЕрдм, рд▓рд╛рдн рд╣реИ, рд╡рд╛рд░реНрддрд╛рд▓рд╛рдк / рд╕рдореАрдХреНрд╖рд╛ / рдкрд░рд┐рд╡рд░реНрддрди рдХрд╛ рдПрдХрд▓ рдмрд┐рдВрджреБ рдЬреИрд╕рд╛ рдХрд┐ рдореИрдВрдиреЗ рдКрдкрд░ рдЙрд▓реНрд▓реЗрдЦ рдХрд┐рдпрд╛ рд╣реИ - рдЗрд╕рдХреЗ рд▓рд┐рдП рдПрдХ рдкреИрдЪ рдХреЗ рд╕рд╛рде рдкрд╣рд▓реЗ рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж, рд╣рд╛рд▓рд╛рдВрдХрд┐, рдореИрдВ рджреЗрдЦ рд░рд╣рд╛ рдерд╛ рдЙрд╕ рд╕рдордп рдЬрдм рдореИрдВрдиреЗ PR . рдмрдирд╛рдпрд╛

рд╕реВрдбреЛ рдХреЛ рдЕрднреА рд╕рдореВрд╣ рдореЗрдВ рдЬреЛрдбрд╝рд╛ рдЬрд╛ рд░рд╣рд╛ рд╣реИ! рджреЗрдЦреЗрдВ #1999

рдХреНрдпрд╛ рдпрд╣ рдкреГрд╖реНрда рдЙрдкрдпреЛрдЧреА рдерд╛?
0 / 5 - 0 рд░реЗрдЯрд┐рдВрдЧреНрд╕

рд╕рдВрдмрдВрдзрд┐рдд рдореБрджреНрджреЛрдВ

zhaoguixu picture zhaoguixu  ┬╖  5рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

supriyopaul picture supriyopaul  ┬╖  4рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

jmcgrath207 picture jmcgrath207  ┬╖  5рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

acdha picture acdha  ┬╖  4рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

TimotheeJeannin picture TimotheeJeannin  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ