32
32
CloseInstance ,
33
33
Create ,
34
34
Create2 ,
35
+ CreateContainer ,
36
+ CreateTTL ,
35
37
Delete ,
36
38
Exists ,
37
39
GetChildren ,
@@ -873,7 +875,8 @@ def sync(self, path):
873
875
return self .sync_async (path ).get ()
874
876
875
877
def create (self , path , value = b"" , acl = None , ephemeral = False ,
876
- sequence = False , makepath = False , include_data = False ):
878
+ sequence = False , makepath = False , include_data = False ,
879
+ container = False , ttl = 0 ):
877
880
"""Create a node with the given value as its data. Optionally
878
881
set an ACL on the node.
879
882
@@ -950,15 +953,19 @@ def create(self, path, value=b"", acl=None, ephemeral=False,
950
953
The `makepath` option.
951
954
.. versionadded:: 2.7
952
955
The `include_data` option.
956
+ .. versionadded:: 2.8
957
+ The container and ttl options.
958
+
953
959
"""
954
960
acl = acl or self .default_acl
955
961
return self .create_async (
956
962
path , value , acl = acl , ephemeral = ephemeral ,
957
- sequence = sequence , makepath = makepath , include_data = include_data
958
- ).get ()
963
+ sequence = sequence , makepath = makepath , include_data = include_data ,
964
+ container = container , ttl = ttl ).get ()
959
965
960
966
def create_async (self , path , value = b"" , acl = None , ephemeral = False ,
961
- sequence = False , makepath = False , include_data = False ):
967
+ sequence = False , makepath = False , include_data = False ,
968
+ container = False , ttl = 0 ):
962
969
"""Asynchronously create a ZNode. Takes the same arguments as
963
970
:meth:`create`.
964
971
@@ -967,7 +974,9 @@ def create_async(self, path, value=b"", acl=None, ephemeral=False,
967
974
.. versionadded:: 1.1
968
975
The makepath option.
969
976
.. versionadded:: 2.7
970
- The `include_data` option.
977
+ The include_data option.
978
+ .. versionadded:: 2.8
979
+ The container and ttl options.
971
980
"""
972
981
if acl is None and self .default_acl :
973
982
acl = self .default_acl
@@ -988,24 +997,86 @@ def create_async(self, path, value=b"", acl=None, ephemeral=False,
988
997
raise TypeError ("Invalid type for 'makepath' (bool expected)" )
989
998
if not isinstance (include_data , bool ):
990
999
raise TypeError ("Invalid type for 'include_data' (bool expected)" )
991
-
1000
+ if not isinstance (container , bool ):
1001
+ raise TypeError ("Invalid type for 'container' (bool expected)" )
1002
+ if not isinstance (ttl , int ) or ttl < 0 :
1003
+ raise TypeError ("Invalid 'ttl' (integer >= 0 expected)" )
1004
+ if ttl and ephemeral :
1005
+ raise TypeError ("Invalid node creation: ephemeral & ttl" )
1006
+ if container and (ephemeral or sequence or ttl ):
1007
+ raise TypeError ("Invalid node creation: container & ephemeral/sequence/ttl" )
1008
+
1009
+ # Should match Zookeeper's CreateMode fromFlag
1010
+ # https://github.com/apache/zookeeper/blob/master/zookeeper-server/src/main/java/org/apache/zookeeper/CreateMode.java#L112
992
1011
flags = 0
993
1012
if ephemeral :
994
1013
flags |= 1
995
1014
if sequence :
996
1015
flags |= 2
1016
+ if container :
1017
+ flags = 4
1018
+ if ttl :
1019
+ if sequence :
1020
+ flags = 6
1021
+ else :
1022
+ flags = 5
1023
+
997
1024
if acl is None :
998
1025
acl = OPEN_ACL_UNSAFE
999
1026
1027
+ # Figure out the OpCode we are going to send
1028
+ if include_data :
1029
+ stat_in_result = True
1030
+ opcode = lambda path , value , acl : Create2 (
1031
+ _prefix_root (self .chroot , path , trailing = sequence ),
1032
+ value ,
1033
+ acl ,
1034
+ flags
1035
+ )
1036
+ elif container :
1037
+ stat_in_result = True
1038
+ opcode = lambda path , value , acl : CreateContainer (
1039
+ _prefix_root (self .chroot , path , trailing = False ),
1040
+ value ,
1041
+ acl ,
1042
+ flags
1043
+ )
1044
+ elif ttl :
1045
+ stat_in_result = True
1046
+ opcode = lambda path , value , acl : CreateTTL (
1047
+ _prefix_root (self .chroot , path , trailing = sequence ),
1048
+ value ,
1049
+ acl ,
1050
+ flags ,
1051
+ ttl
1052
+ )
1053
+ else :
1054
+ stat_in_result = False
1055
+ opcode = lambda path , value , acl : Create (
1056
+ _prefix_root (self .chroot , path , trailing = sequence ),
1057
+ value ,
1058
+ acl ,
1059
+ flags
1060
+ )
1000
1061
async_result = self .handler .async_result ()
1001
1062
1002
1063
@capture_exceptions (async_result )
1003
1064
def do_create ():
1004
- result = self ._create_async_inner (
1005
- path , value , acl , flags ,
1006
- trailing = sequence , include_data = include_data
1065
+ inner_async_result = self .handler .async_result ()
1066
+
1067
+ call_result = self ._call (
1068
+ opcode (path , value , acl ),
1069
+ inner_async_result
1007
1070
)
1008
- result .rawlink (create_completion )
1071
+ if call_result is False :
1072
+ # We hit a short-circuit exit on the _call. Because we are
1073
+ # not using the original async_result here, we bubble the
1074
+ # exception upwards to the do_create function in
1075
+ # KazooClient.create so that it gets set on the correct
1076
+ # async_result object
1077
+ raise inner_async_result .exception
1078
+
1079
+ inner_async_result .rawlink (create_completion )
1009
1080
1010
1081
@capture_exceptions (async_result )
1011
1082
def retry_completion (result ):
@@ -1015,7 +1086,7 @@ def retry_completion(result):
1015
1086
@wrap (async_result )
1016
1087
def create_completion (result ):
1017
1088
try :
1018
- if include_data :
1089
+ if stat_in_result :
1019
1090
new_path , stat = result .get ()
1020
1091
return self .unchroot (new_path ), stat
1021
1092
else :
@@ -1032,26 +1103,6 @@ def create_completion(result):
1032
1103
do_create ()
1033
1104
return async_result
1034
1105
1035
- def _create_async_inner (self , path , value , acl , flags ,
1036
- trailing = False , include_data = False ):
1037
- async_result = self .handler .async_result ()
1038
- if include_data :
1039
- opcode = Create2
1040
- else :
1041
- opcode = Create
1042
-
1043
- call_result = self ._call (
1044
- opcode (_prefix_root (self .chroot , path , trailing = trailing ),
1045
- value , acl , flags ), async_result )
1046
- if call_result is False :
1047
- # We hit a short-circuit exit on the _call. Because we are
1048
- # not using the original async_result here, we bubble the
1049
- # exception upwards to the do_create function in
1050
- # KazooClient.create so that it gets set on the correct
1051
- # async_result object
1052
- raise async_result .exception
1053
- return async_result
1054
-
1055
1106
def ensure_path (self , path , acl = None ):
1056
1107
"""Recursively create a path if it doesn't exist.
1057
1108
@@ -1590,13 +1641,15 @@ def __init__(self, client):
1590
1641
self .committed = False
1591
1642
1592
1643
def create (self , path , value = b"" , acl = None , ephemeral = False ,
1593
- sequence = False ):
1644
+ sequence = False , include_data = False , container = False , ttl = 0 ):
1594
1645
"""Add a create ZNode to the transaction. Takes the same
1595
1646
arguments as :meth:`KazooClient.create`, with the exception
1596
1647
of `makepath`.
1597
1648
1598
1649
:returns: None
1599
1650
1651
+ .. versionadded:: 2.8
1652
+ The include_data, container and ttl options.
1600
1653
"""
1601
1654
if acl is None and self .client .default_acl :
1602
1655
acl = self .client .default_acl
@@ -1612,17 +1665,67 @@ def create(self, path, value=b"", acl=None, ephemeral=False,
1612
1665
raise TypeError ("Invalid type for 'ephemeral' (bool expected)" )
1613
1666
if not isinstance (sequence , bool ):
1614
1667
raise TypeError ("Invalid type for 'sequence' (bool expected)" )
1615
-
1668
+ if not isinstance (include_data , bool ):
1669
+ raise TypeError ("Invalid type for 'include_data' (bool expected)" )
1670
+ if not isinstance (container , bool ):
1671
+ raise TypeError ("Invalid type for 'container' (bool expected)" )
1672
+ if not isinstance (ttl , int ) or ttl < 0 :
1673
+ raise TypeError ("Invalid 'ttl' (integer >= 0 expected)" )
1674
+ if ttl and ephemeral :
1675
+ raise TypeError ("Invalid node creation: ephemeral & ttl" )
1676
+ if container and (ephemeral or sequence or ttl ):
1677
+ raise TypeError ("Invalid node creation: container & ephemeral/sequence/ttl" )
1678
+
1679
+ # Should match Zookeeper's CreateMode fromFlag
1680
+ # https://github.com/apache/zookeeper/blob/master/zookeeper-server/src/main/java/org/apache/zookeeper/CreateMode.java#L112
1616
1681
flags = 0
1617
1682
if ephemeral :
1618
1683
flags |= 1
1619
1684
if sequence :
1620
1685
flags |= 2
1686
+ if container :
1687
+ flags = 4
1688
+ if ttl :
1689
+ if sequence :
1690
+ flags = 6
1691
+ else :
1692
+ flags = 5
1693
+
1621
1694
if acl is None :
1622
1695
acl = OPEN_ACL_UNSAFE
1623
1696
1624
- self ._add (Create (_prefix_root (self .client .chroot , path ), value , acl ,
1625
- flags ), None )
1697
+ # Figure out the OpCode we are going to send
1698
+ if include_data :
1699
+ opcode = lambda path , value , acl : Create2 (
1700
+ _prefix_root (self .client .chroot , path , trailing = sequence ),
1701
+ value ,
1702
+ acl ,
1703
+ flags
1704
+ )
1705
+ elif container :
1706
+ opcode = lambda path , value , acl : CreateContainer (
1707
+ _prefix_root (self .client .chroot , path , trailing = False ),
1708
+ value ,
1709
+ acl ,
1710
+ flags
1711
+ )
1712
+ elif ttl :
1713
+ opcode = lambda path , value , acl : CreateTTL (
1714
+ _prefix_root (self .client .chroot , path , trailing = sequence ),
1715
+ value ,
1716
+ acl ,
1717
+ flags ,
1718
+ ttl
1719
+ )
1720
+ else :
1721
+ opcode = lambda path , value , acl : Create (
1722
+ _prefix_root (self .client .chroot , path , trailing = sequence ),
1723
+ value ,
1724
+ acl ,
1725
+ flags
1726
+ )
1727
+
1728
+ self ._add (opcode (path , value , acl ), None )
1626
1729
1627
1730
def delete (self , path , version = - 1 ):
1628
1731
"""Add a delete ZNode to the transaction. Takes the same
0 commit comments