3030    CloseInstance ,
3131    Create ,
3232    Create2 ,
33+     CreateContainer ,
34+     CreateTTL ,
3335    Delete ,
3436    Exists ,
3537    GetChildren ,
@@ -917,6 +919,8 @@ def create(
917919        sequence = False ,
918920        makepath = False ,
919921        include_data = False ,
922+         container = False ,
923+         ttl = 0 ,
920924    ):
921925        """Create a node with the given value as its data. Optionally 
922926        set an ACL on the node. 
@@ -994,6 +998,9 @@ def create(
994998            The `makepath` option. 
995999        .. versionadded:: 2.7 
9961000            The `include_data` option. 
1001+         .. versionadded:: 2.9 
1002+             The `container` and `ttl` options. 
1003+ 
9971004        """ 
9981005        acl  =  acl  or  self .default_acl 
9991006        return  self .create_async (
@@ -1004,6 +1011,8 @@ def create(
10041011            sequence = sequence ,
10051012            makepath = makepath ,
10061013            include_data = include_data ,
1014+             container = container ,
1015+             ttl = ttl ,
10071016        ).get ()
10081017
10091018    def  create_async (
@@ -1015,6 +1024,8 @@ def create_async(
10151024        sequence = False ,
10161025        makepath = False ,
10171026        include_data = False ,
1027+         container = False ,
1028+         ttl = 0 ,
10181029    ):
10191030        """Asynchronously create a ZNode. Takes the same arguments as 
10201031        :meth:`create`. 
@@ -1025,50 +1036,39 @@ def create_async(
10251036            The makepath option. 
10261037        .. versionadded:: 2.7 
10271038            The `include_data` option. 
1039+         .. versionadded:: 2.9 
1040+             The `container` and `ttl` options. 
10281041        """ 
10291042        if  acl  is  None  and  self .default_acl :
10301043            acl  =  self .default_acl 
10311044
1032-         if  not  isinstance (path , str ):
1033-             raise  TypeError ("Invalid type for 'path' (string expected)" )
1034-         if  acl  and  (
1035-             isinstance (acl , ACL ) or  not  isinstance (acl , (tuple , list ))
1036-         ):
1037-             raise  TypeError (
1038-                 "Invalid type for 'acl' (acl must be a tuple/list"  " of ACL's" 
1039-             )
1040-         if  value  is  not   None  and  not  isinstance (value , bytes ):
1041-             raise  TypeError ("Invalid type for 'value' (must be a byte string)" )
1042-         if  not  isinstance (ephemeral , bool ):
1043-             raise  TypeError ("Invalid type for 'ephemeral' (bool expected)" )
1044-         if  not  isinstance (sequence , bool ):
1045-             raise  TypeError ("Invalid type for 'sequence' (bool expected)" )
1046-         if  not  isinstance (makepath , bool ):
1047-             raise  TypeError ("Invalid type for 'makepath' (bool expected)" )
1048-         if  not  isinstance (include_data , bool ):
1049-             raise  TypeError ("Invalid type for 'include_data' (bool expected)" )
1050- 
1051-         flags  =  0 
1052-         if  ephemeral :
1053-             flags  |=  1 
1054-         if  sequence :
1055-             flags  |=  2 
1056-         if  acl  is  None :
1057-             acl  =  OPEN_ACL_UNSAFE 
1058- 
1045+         opcode  =  _create_opcode (
1046+             path ,
1047+             value ,
1048+             acl ,
1049+             self .chroot ,
1050+             ephemeral ,
1051+             sequence ,
1052+             include_data ,
1053+             container ,
1054+             ttl ,
1055+         )
10591056        async_result  =  self .handler .async_result ()
10601057
10611058        @capture_exceptions (async_result ) 
10621059        def  do_create ():
1063-             result  =  self ._create_async_inner (
1064-                 path ,
1065-                 value ,
1066-                 acl ,
1067-                 flags ,
1068-                 trailing = sequence ,
1069-                 include_data = include_data ,
1070-             )
1071-             result .rawlink (create_completion )
1060+             inner_async_result  =  self .handler .async_result ()
1061+ 
1062+             call_result  =  self ._call (opcode , inner_async_result )
1063+             if  call_result  is  False :
1064+                 # We hit a short-circuit exit on the _call. Because we are 
1065+                 # not using the original async_result here, we bubble the 
1066+                 # exception upwards to the do_create function in 
1067+                 # KazooClient.create so that it gets set on the correct 
1068+                 # async_result object 
1069+                 raise  inner_async_result .exception 
1070+ 
1071+             inner_async_result .rawlink (create_completion )
10721072
10731073        @capture_exceptions (async_result ) 
10741074        def  retry_completion (result ):
@@ -1078,11 +1078,11 @@ def retry_completion(result):
10781078        @wrap (async_result ) 
10791079        def  create_completion (result ):
10801080            try :
1081-                 if  include_data :
1081+                 if  opcode .type  ==  Create .type :
1082+                     return  self .unchroot (result .get ())
1083+                 else :
10821084                    new_path , stat  =  result .get ()
10831085                    return  self .unchroot (new_path ), stat 
1084-                 else :
1085-                     return  self .unchroot (result .get ())
10861086            except  NoNodeError :
10871087                if  not  makepath :
10881088                    raise 
@@ -1095,33 +1095,6 @@ def create_completion(result):
10951095        do_create ()
10961096        return  async_result 
10971097
1098-     def  _create_async_inner (
1099-         self , path , value , acl , flags , trailing = False , include_data = False 
1100-     ):
1101-         async_result  =  self .handler .async_result ()
1102-         if  include_data :
1103-             opcode  =  Create2 
1104-         else :
1105-             opcode  =  Create 
1106- 
1107-         call_result  =  self ._call (
1108-             opcode (
1109-                 _prefix_root (self .chroot , path , trailing = trailing ),
1110-                 value ,
1111-                 acl ,
1112-                 flags ,
1113-             ),
1114-             async_result ,
1115-         )
1116-         if  call_result  is  False :
1117-             # We hit a short-circuit exit on the _call. Because we are 
1118-             # not using the original async_result here, we bubble the 
1119-             # exception upwards to the do_create function in 
1120-             # KazooClient.create so that it gets set on the correct 
1121-             # async_result object 
1122-             raise  async_result .exception 
1123-         return  async_result 
1124- 
11251098    def  ensure_path (self , path , acl = None ):
11261099        """Recursively create a path if it doesn't exist. 
11271100
@@ -1680,48 +1653,33 @@ def create(
16801653        ephemeral = False ,
16811654        sequence = False ,
16821655        include_data = False ,
1656+         container = False ,
1657+         ttl = 0 ,
16831658    ):
16841659        """Add a create ZNode to the transaction. Takes the same 
16851660        arguments as :meth:`KazooClient.create`, with the exception 
16861661        of `makepath`. 
16871662
16881663        :returns: None 
16891664
1665+         .. versionadded:: 2.9 
1666+             The `include_data`, `container` and `ttl` options. 
16901667        """ 
16911668        if  acl  is  None  and  self .client .default_acl :
16921669            acl  =  self .client .default_acl 
16931670
1694-         if  not  isinstance (path , str ):
1695-             raise  TypeError ("Invalid type for 'path' (string expected)" )
1696-         if  acl  and  not  isinstance (acl , (tuple , list )):
1697-             raise  TypeError (
1698-                 "Invalid type for 'acl' (acl must be a tuple/list"  " of ACL's" 
1699-             )
1700-         if  not  isinstance (value , bytes ):
1701-             raise  TypeError ("Invalid type for 'value' (must be a byte string)" )
1702-         if  not  isinstance (ephemeral , bool ):
1703-             raise  TypeError ("Invalid type for 'ephemeral' (bool expected)" )
1704-         if  not  isinstance (sequence , bool ):
1705-             raise  TypeError ("Invalid type for 'sequence' (bool expected)" )
1706-         if  not  isinstance (include_data , bool ):
1707-             raise  TypeError ("Invalid type for 'include_data' (bool expected)" )
1708- 
1709-         flags  =  0 
1710-         if  ephemeral :
1711-             flags  |=  1 
1712-         if  sequence :
1713-             flags  |=  2 
1714-         if  acl  is  None :
1715-             acl  =  OPEN_ACL_UNSAFE 
1716-         if  include_data :
1717-             opcode  =  Create2 
1718-         else :
1719-             opcode  =  Create 
1720- 
1721-         self ._add (
1722-             opcode (_prefix_root (self .client .chroot , path ), value , acl , flags ),
1723-             None ,
1671+         opcode  =  _create_opcode (
1672+             path ,
1673+             value ,
1674+             acl ,
1675+             self .client .chroot ,
1676+             ephemeral ,
1677+             sequence ,
1678+             include_data ,
1679+             container ,
1680+             ttl ,
17241681        )
1682+         self ._add (opcode , None )
17251683
17261684    def  delete (self , path , version = - 1 ):
17271685        """Add a delete ZNode to the transaction. Takes the same 
@@ -1802,3 +1760,85 @@ def _add(self, request, post_processor=None):
18021760        self ._check_tx_state ()
18031761        self .client .logger .log (BLATHER , "Added %r to %r" , request , self )
18041762        self .operations .append (request )
1763+ 
1764+ 
1765+ def  _create_opcode (
1766+     path ,
1767+     value ,
1768+     acl ,
1769+     chroot ,
1770+     ephemeral ,
1771+     sequence ,
1772+     include_data ,
1773+     container ,
1774+     ttl ,
1775+ ):
1776+     """Helper function. 
1777+     Creates the create OpCode for regular `client.create()` operations as 
1778+     well as in a `client.transaction()` context. 
1779+     """ 
1780+     if  not  isinstance (path , string_types ):
1781+         raise  TypeError ("Invalid type for 'path' (string expected)" )
1782+     if  acl  and  (isinstance (acl , ACL ) or  not  isinstance (acl , (tuple , list ))):
1783+         raise  TypeError (
1784+             "Invalid type for 'acl' (acl must be a tuple/list"  " of ACL's" 
1785+         )
1786+     if  value  is  not   None  and  not  isinstance (value , bytes_types ):
1787+         raise  TypeError ("Invalid type for 'value' (must be a byte string)" )
1788+     if  not  isinstance (ephemeral , bool ):
1789+         raise  TypeError ("Invalid type for 'ephemeral' (bool expected)" )
1790+     if  not  isinstance (sequence , bool ):
1791+         raise  TypeError ("Invalid type for 'sequence' (bool expected)" )
1792+     if  not  isinstance (include_data , bool ):
1793+         raise  TypeError ("Invalid type for 'include_data' (bool expected)" )
1794+     if  not  isinstance (container , bool ):
1795+         raise  TypeError ("Invalid type for 'container' (bool expected)" )
1796+     if  not  isinstance (ttl , int ) or  ttl  <  0 :
1797+         raise  TypeError ("Invalid 'ttl' (integer >= 0 expected)" )
1798+     if  ttl  and  ephemeral :
1799+         raise  TypeError ("Invalid node creation: ephemeral & ttl" )
1800+     if  container  and  (ephemeral  or  sequence  or  ttl ):
1801+         raise  TypeError (
1802+             "Invalid node creation: container & ephemeral/sequence/ttl" 
1803+         )
1804+ 
1805+     # Should match Zookeeper's CreateMode fromFlag 
1806+     # https://github.com/apache/zookeeper/blob/master/zookeeper-server/ 
1807+     # src/main/java/org/apache/zookeeper/CreateMode.java#L112 
1808+     flags  =  0 
1809+     if  ephemeral :
1810+         flags  |=  1 
1811+     if  sequence :
1812+         flags  |=  2 
1813+     if  container :
1814+         flags  =  4 
1815+     if  ttl :
1816+         if  sequence :
1817+             flags  =  6 
1818+         else :
1819+             flags  =  5 
1820+ 
1821+     if  acl  is  None :
1822+         acl  =  OPEN_ACL_UNSAFE 
1823+ 
1824+     # Figure out the OpCode we are going to send 
1825+     if  include_data :
1826+         return  Create2 (
1827+             _prefix_root (chroot , path , trailing = sequence ), value , acl , flags 
1828+         )
1829+     elif  container :
1830+         return  CreateContainer (
1831+             _prefix_root (chroot , path , trailing = False ), value , acl , flags 
1832+         )
1833+     elif  ttl :
1834+         return  CreateTTL (
1835+             _prefix_root (chroot , path , trailing = sequence ),
1836+             value ,
1837+             acl ,
1838+             flags ,
1839+             ttl ,
1840+         )
1841+     else :
1842+         return  Create (
1843+             _prefix_root (chroot , path , trailing = sequence ), value , acl , flags 
1844+         )
0 commit comments