30
30
CloseInstance ,
31
31
Create ,
32
32
Create2 ,
33
+ CreateContainer ,
34
+ CreateTTL ,
33
35
Delete ,
34
36
Exists ,
35
37
GetChildren ,
@@ -917,6 +919,8 @@ def create(
917
919
sequence = False ,
918
920
makepath = False ,
919
921
include_data = False ,
922
+ container = False ,
923
+ ttl = 0 ,
920
924
):
921
925
"""Create a node with the given value as its data. Optionally
922
926
set an ACL on the node.
@@ -994,6 +998,9 @@ def create(
994
998
The `makepath` option.
995
999
.. versionadded:: 2.7
996
1000
The `include_data` option.
1001
+ .. versionadded:: 2.9
1002
+ The `container` and `ttl` options.
1003
+
997
1004
"""
998
1005
acl = acl or self .default_acl
999
1006
return self .create_async (
@@ -1004,6 +1011,8 @@ def create(
1004
1011
sequence = sequence ,
1005
1012
makepath = makepath ,
1006
1013
include_data = include_data ,
1014
+ container = container ,
1015
+ ttl = ttl ,
1007
1016
).get ()
1008
1017
1009
1018
def create_async (
@@ -1015,6 +1024,8 @@ def create_async(
1015
1024
sequence = False ,
1016
1025
makepath = False ,
1017
1026
include_data = False ,
1027
+ container = False ,
1028
+ ttl = 0 ,
1018
1029
):
1019
1030
"""Asynchronously create a ZNode. Takes the same arguments as
1020
1031
:meth:`create`.
@@ -1025,50 +1036,39 @@ def create_async(
1025
1036
The makepath option.
1026
1037
.. versionadded:: 2.7
1027
1038
The `include_data` option.
1039
+ .. versionadded:: 2.9
1040
+ The `container` and `ttl` options.
1028
1041
"""
1029
1042
if acl is None and self .default_acl :
1030
1043
acl = self .default_acl
1031
1044
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
+ )
1059
1056
async_result = self .handler .async_result ()
1060
1057
1061
1058
@capture_exceptions (async_result )
1062
1059
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 )
1072
1072
1073
1073
@capture_exceptions (async_result )
1074
1074
def retry_completion (result ):
@@ -1078,11 +1078,11 @@ def retry_completion(result):
1078
1078
@wrap (async_result )
1079
1079
def create_completion (result ):
1080
1080
try :
1081
- if include_data :
1081
+ if opcode .type == Create .type :
1082
+ return self .unchroot (result .get ())
1083
+ else :
1082
1084
new_path , stat = result .get ()
1083
1085
return self .unchroot (new_path ), stat
1084
- else :
1085
- return self .unchroot (result .get ())
1086
1086
except NoNodeError :
1087
1087
if not makepath :
1088
1088
raise
@@ -1095,33 +1095,6 @@ def create_completion(result):
1095
1095
do_create ()
1096
1096
return async_result
1097
1097
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
-
1125
1098
def ensure_path (self , path , acl = None ):
1126
1099
"""Recursively create a path if it doesn't exist.
1127
1100
@@ -1680,48 +1653,33 @@ def create(
1680
1653
ephemeral = False ,
1681
1654
sequence = False ,
1682
1655
include_data = False ,
1656
+ container = False ,
1657
+ ttl = 0 ,
1683
1658
):
1684
1659
"""Add a create ZNode to the transaction. Takes the same
1685
1660
arguments as :meth:`KazooClient.create`, with the exception
1686
1661
of `makepath`.
1687
1662
1688
1663
:returns: None
1689
1664
1665
+ .. versionadded:: 2.9
1666
+ The `include_data`, `container` and `ttl` options.
1690
1667
"""
1691
1668
if acl is None and self .client .default_acl :
1692
1669
acl = self .client .default_acl
1693
1670
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 ,
1724
1681
)
1682
+ self ._add (opcode , None )
1725
1683
1726
1684
def delete (self , path , version = - 1 ):
1727
1685
"""Add a delete ZNode to the transaction. Takes the same
@@ -1802,3 +1760,85 @@ def _add(self, request, post_processor=None):
1802
1760
self ._check_tx_state ()
1803
1761
self .client .logger .log (BLATHER , "Added %r to %r" , request , self )
1804
1762
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