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,45 +974,35 @@ 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
974
-
975
- if not isinstance (path , string_types ):
976
- raise TypeError ("Invalid type for 'path' (string expected)" )
977
- if acl and (isinstance (acl , ACL ) or
978
- not isinstance (acl , (tuple , list ))):
979
- raise TypeError ("Invalid type for 'acl' (acl must be a tuple/list"
980
- " of ACL's" )
981
- if value is not None and not isinstance (value , bytes_types ):
982
- raise TypeError ("Invalid type for 'value' (must be a byte string)" )
983
- if not isinstance (ephemeral , bool ):
984
- raise TypeError ("Invalid type for 'ephemeral' (bool expected)" )
985
- if not isinstance (sequence , bool ):
986
- raise TypeError ("Invalid type for 'sequence' (bool expected)" )
987
983
if not isinstance (makepath , bool ):
988
984
raise TypeError ("Invalid type for 'makepath' (bool expected)" )
989
- if not isinstance (include_data , bool ):
990
- raise TypeError ("Invalid type for 'include_data' (bool expected)" )
991
-
992
- flags = 0
993
- if ephemeral :
994
- flags |= 1
995
- if sequence :
996
- flags |= 2
997
- if acl is None :
998
- acl = OPEN_ACL_UNSAFE
999
985
986
+ opcode = _create_opcode (
987
+ path , value , acl , self .chroot ,
988
+ ephemeral , sequence , include_data , container , ttl
989
+ )
1000
990
async_result = self .handler .async_result ()
1001
991
1002
992
@capture_exceptions (async_result )
1003
993
def do_create ():
1004
- result = self ._create_async_inner (
1005
- path , value , acl , flags ,
1006
- trailing = sequence , include_data = include_data
1007
- )
1008
- result .rawlink (create_completion )
994
+ inner_async_result = self .handler .async_result ()
995
+
996
+ call_result = self ._call (opcode , inner_async_result )
997
+ if call_result is False :
998
+ # We hit a short-circuit exit on the _call. Because we are
999
+ # not using the original async_result here, we bubble the
1000
+ # exception upwards to the do_create function in
1001
+ # KazooClient.create so that it gets set on the correct
1002
+ # async_result object
1003
+ raise inner_async_result .exception
1004
+
1005
+ inner_async_result .rawlink (create_completion )
1009
1006
1010
1007
@capture_exceptions (async_result )
1011
1008
def retry_completion (result ):
@@ -1015,11 +1012,11 @@ def retry_completion(result):
1015
1012
@wrap (async_result )
1016
1013
def create_completion (result ):
1017
1014
try :
1018
- if include_data :
1015
+ if opcode .type == Create .type :
1016
+ return self .unchroot (result .get ())
1017
+ else :
1019
1018
new_path , stat = result .get ()
1020
1019
return self .unchroot (new_path ), stat
1021
- else :
1022
- return self .unchroot (result .get ())
1023
1020
except NoNodeError :
1024
1021
if not makepath :
1025
1022
raise
@@ -1032,26 +1029,6 @@ def create_completion(result):
1032
1029
do_create ()
1033
1030
return async_result
1034
1031
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
1032
def ensure_path (self , path , acl = None ):
1056
1033
"""Recursively create a path if it doesn't exist.
1057
1034
@@ -1590,39 +1567,24 @@ def __init__(self, client):
1590
1567
self .committed = False
1591
1568
1592
1569
def create (self , path , value = b"" , acl = None , ephemeral = False ,
1593
- sequence = False ):
1570
+ sequence = False , include_data = False , container = False , ttl = 0 ):
1594
1571
"""Add a create ZNode to the transaction. Takes the same
1595
1572
arguments as :meth:`KazooClient.create`, with the exception
1596
1573
of `makepath`.
1597
1574
1598
1575
:returns: None
1599
1576
1577
+ .. versionadded:: 2.8
1578
+ The include_data, container and ttl options.
1600
1579
"""
1601
1580
if acl is None and self .client .default_acl :
1602
1581
acl = self .client .default_acl
1603
1582
1604
- if not isinstance (path , string_types ):
1605
- raise TypeError ("Invalid type for 'path' (string expected)" )
1606
- if acl and not isinstance (acl , (tuple , list )):
1607
- raise TypeError ("Invalid type for 'acl' (acl must be a tuple/list"
1608
- " of ACL's" )
1609
- if not isinstance (value , bytes_types ):
1610
- raise TypeError ("Invalid type for 'value' (must be a byte string)" )
1611
- if not isinstance (ephemeral , bool ):
1612
- raise TypeError ("Invalid type for 'ephemeral' (bool expected)" )
1613
- if not isinstance (sequence , bool ):
1614
- raise TypeError ("Invalid type for 'sequence' (bool expected)" )
1615
-
1616
- flags = 0
1617
- if ephemeral :
1618
- flags |= 1
1619
- if sequence :
1620
- flags |= 2
1621
- if acl is None :
1622
- acl = OPEN_ACL_UNSAFE
1623
-
1624
- self ._add (Create (_prefix_root (self .client .chroot , path ), value , acl ,
1625
- flags ), None )
1583
+ opcode = _create_opcode (
1584
+ path , value , acl , self .client .chroot ,
1585
+ ephemeral , sequence , include_data , container , ttl
1586
+ )
1587
+ self ._add (opcode , None )
1626
1588
1627
1589
def delete (self , path , version = - 1 ):
1628
1590
"""Add a delete ZNode to the transaction. Takes the same
@@ -1701,3 +1663,85 @@ def _add(self, request, post_processor=None):
1701
1663
self ._check_tx_state ()
1702
1664
self .client .logger .log (BLATHER , 'Added %r to %r' , request , self )
1703
1665
self .operations .append (request )
1666
+
1667
+
1668
+ def _create_opcode (path , value , acl , chroot ,
1669
+ ephemeral , sequence , include_data , container , ttl ):
1670
+ """Helper function.
1671
+ Creates the create OpCode for regular `client.create()` operations as
1672
+ well as in a `client.transaction()` context.
1673
+ """
1674
+ if not isinstance (path , string_types ):
1675
+ raise TypeError ("Invalid type for 'path' (string expected)" )
1676
+ if acl and (isinstance (acl , ACL ) or
1677
+ not isinstance (acl , (tuple , list ))):
1678
+ raise TypeError ("Invalid type for 'acl' (acl must be a tuple/list"
1679
+ " of ACL's" )
1680
+ if value is not None and not isinstance (value , bytes_types ):
1681
+ raise TypeError ("Invalid type for 'value' (must be a byte string)" )
1682
+ if not isinstance (ephemeral , bool ):
1683
+ raise TypeError ("Invalid type for 'ephemeral' (bool expected)" )
1684
+ if not isinstance (sequence , bool ):
1685
+ raise TypeError ("Invalid type for 'sequence' (bool expected)" )
1686
+ if not isinstance (include_data , bool ):
1687
+ raise TypeError ("Invalid type for 'include_data' (bool expected)" )
1688
+ if not isinstance (container , bool ):
1689
+ raise TypeError ("Invalid type for 'container' (bool expected)" )
1690
+ if not isinstance (ttl , int ) or ttl < 0 :
1691
+ raise TypeError ("Invalid 'ttl' (integer >= 0 expected)" )
1692
+ if ttl and ephemeral :
1693
+ raise TypeError ("Invalid node creation: ephemeral & ttl" )
1694
+ if container and (ephemeral or sequence or ttl ):
1695
+ raise TypeError (
1696
+ "Invalid node creation: container & ephemeral/sequence/ttl"
1697
+ )
1698
+
1699
+ # Should match Zookeeper's CreateMode fromFlag
1700
+ # https://github.com/apache/zookeeper/blob/master/zookeeper-server/
1701
+ # src/main/java/org/apache/zookeeper/CreateMode.java#L112
1702
+ flags = 0
1703
+ if ephemeral :
1704
+ flags |= 1
1705
+ if sequence :
1706
+ flags |= 2
1707
+ if container :
1708
+ flags = 4
1709
+ if ttl :
1710
+ if sequence :
1711
+ flags = 6
1712
+ else :
1713
+ flags = 5
1714
+
1715
+ if acl is None :
1716
+ acl = OPEN_ACL_UNSAFE
1717
+
1718
+ # Figure out the OpCode we are going to send
1719
+ if include_data :
1720
+ return Create2 (
1721
+ _prefix_root (chroot , path , trailing = sequence ),
1722
+ value ,
1723
+ acl ,
1724
+ flags
1725
+ )
1726
+ elif container :
1727
+ return CreateContainer (
1728
+ _prefix_root (chroot , path , trailing = False ),
1729
+ value ,
1730
+ acl ,
1731
+ flags
1732
+ )
1733
+ elif ttl :
1734
+ return CreateTTL (
1735
+ _prefix_root (chroot , path , trailing = sequence ),
1736
+ value ,
1737
+ acl ,
1738
+ flags ,
1739
+ ttl
1740
+ )
1741
+ else :
1742
+ return Create (
1743
+ _prefix_root (chroot , path , trailing = sequence ),
1744
+ value ,
1745
+ acl ,
1746
+ flags
1747
+ )
0 commit comments