4
4
"""
5
5
Confluence Cloud API implementation
6
6
"""
7
+ import functools
8
+ import json
7
9
import logging
10
+ import re
8
11
import warnings
9
12
from typing import Any , Dict , List , Optional , Tuple , Union
10
13
@@ -31,6 +34,14 @@ def __init__(self, url: str, *args, **kwargs):
31
34
kwargs .setdefault ("api_version" , 2 )
32
35
super ().__init__ (url , * args , ** kwargs )
33
36
37
+ # Initialize the compatibility method mapping
38
+ self ._compatibility_method_mapping = {}
39
+
40
+ # Add compatibility mapping here if needed
41
+ # self._compatibility_method_mapping = {
42
+ # "old_method_name": "new_method_name"
43
+ # }
44
+
34
45
# Warn about V1 method usage
35
46
warnings .warn (
36
47
"V1 methods are deprecated in ConfluenceCloud. Use V2 methods instead." , DeprecationWarning , stacklevel = 2
@@ -49,7 +60,7 @@ def __getattr__(self, name):
49
60
Raises:
50
61
AttributeError: If no mapping exists and the attribute isn't found
51
62
"""
52
- if name in self ._compatibility_method_mapping :
63
+ if hasattr ( self , "_compatibility_method_mapping" ) and name in self ._compatibility_method_mapping :
53
64
v2_method_name = self ._compatibility_method_mapping [name ]
54
65
v2_method = getattr (self , v2_method_name )
55
66
@@ -840,37 +851,35 @@ def get_page_property_by_key(self, page_id: str, property_key: str) -> Dict[str,
840
851
log .error (f"Failed to retrieve property { property_key } for page { page_id } : { e } " )
841
852
raise
842
853
843
- def create_page_property (self , page_id : str , property_key : str , property_value : Any ) -> Dict [str , Any ]:
854
+ def create_page_property (self , page_id : str , key : str , value : Any ) -> Dict [str , Any ]:
844
855
"""
845
856
Creates a new property for a page.
846
857
847
858
Args:
848
859
page_id: The ID of the page
849
- property_key : The key of the property to create. Must only contain alphanumeric
850
- characters and periods
851
- property_value : The value of the property. Can be any JSON-serializable value
860
+ key : The key of the property to create. Must only contain alphanumeric
861
+ characters and periods
862
+ value : The value of the property. Can be any JSON-serializable value
852
863
853
864
Returns:
854
- The created page property object
865
+ The created property object
855
866
856
867
Raises:
857
868
HTTPError: If the API call fails
858
- ValueError: If the property_key has invalid characters
869
+ ValueError: If the key has invalid characters
859
870
"""
860
871
# Validate key format
861
- import re
862
-
863
- if not re .match (r"^[a-zA-Z0-9.]+$" , property_key ):
872
+ if not re .match (r"^[a-zA-Z0-9.]+$" , key ):
864
873
raise ValueError ("Property key must only contain alphanumeric characters and periods." )
865
874
866
875
endpoint = self .get_endpoint ("page_properties" , id = page_id )
867
876
868
- data = {"key" : property_key , "value" : property_value }
877
+ data = {"key" : key , "value" : value }
869
878
870
879
try :
871
880
return self .post (endpoint , data = data )
872
881
except Exception as e :
873
- log .error (f"Failed to create property { property_key } for page { page_id } : { e } " )
882
+ log .error (f"Failed to create property { key } for page { page_id } : { e } " )
874
883
raise
875
884
876
885
def update_page_property (
@@ -2121,7 +2130,7 @@ def get_custom_content(
2121
2130
page_id: (optional) Filter by page ID
2122
2131
blog_post_id: (optional) Filter by blog post ID
2123
2132
custom_content_id: (optional) Filter by parent custom content ID
2124
- id : (optional) List of custom content IDs to filter by
2133
+ ids : (optional) List of custom content IDs to filter by
2125
2134
status: (optional) Filter by status. Valid values: "current", "draft", "archived", "trashed", "deleted", "any"
2126
2135
body_format: (optional) Format to retrieve the body in.
2127
2136
Valid values: "storage", "atlas_doc_format", "raw", "view"
@@ -2151,19 +2160,203 @@ def get_custom_content(
2151
2160
if ids :
2152
2161
params ["id" ] = "," .join (ids )
2153
2162
if status :
2154
- params ["id" ] = "," .join (ids )
2163
+ params ["status" ] = status
2164
+ if body_format :
2165
+ params ["body-format" ] = body_format
2166
+ if sort :
2167
+ params ["sort" ] = sort
2168
+ if limit :
2169
+ params ["limit" ] = limit
2170
+ if cursor :
2171
+ params ["cursor" ] = cursor
2155
2172
2156
- if key :
2157
- params ["key" ] = "," .join (key )
2173
+ try :
2174
+ return list (self ._get_paged (endpoint , params = params ))
2175
+ except Exception as e :
2176
+ log .error (f"Failed to retrieve custom content: { e } " )
2177
+ raise
2158
2178
2159
- if space_id :
2160
- params ["spaceId" ] = space_id
2179
+ def add_custom_content_label (self , custom_content_id : str , label : str , prefix : str = "global" ) -> Dict [str , Any ]:
2180
+ """
2181
+ Adds a label to custom content.
2182
+
2183
+ Args:
2184
+ custom_content_id: The ID of the custom content
2185
+ label: The label to add
2186
+ prefix: (optional) The prefix of the label. Default is "global"
2187
+
2188
+ Returns:
2189
+ The created label object
2190
+
2191
+ Raises:
2192
+ HTTPError: If the API call fails
2193
+ ValueError: If the label is invalid
2194
+ """
2195
+ if not label :
2196
+ raise ValueError ("Label cannot be empty" )
2197
+
2198
+ endpoint = self .get_endpoint ("custom_content_labels" , id = custom_content_id )
2199
+
2200
+ data = {"name" : label , "prefix" : prefix }
2201
+
2202
+ try :
2203
+ return self .post (endpoint , data = data )
2204
+ except Exception as e :
2205
+ log .error (f"Failed to add label '{ label } ' to custom content { custom_content_id } : { e } " )
2206
+ raise
2207
+
2208
+ def delete_custom_content_label (self , custom_content_id : str , label : str , prefix : str = "global" ) -> bool :
2209
+ """
2210
+ Delete a label from custom content.
2211
+
2212
+ Args:
2213
+ custom_content_id: The ID of the custom content
2214
+ label: The label to delete
2215
+ prefix: (optional) The prefix of the label. Default is "global"
2216
+
2217
+ Returns:
2218
+ True if the label was successfully deleted, False otherwise
2219
+
2220
+ Raises:
2221
+ HTTPError: If the API call fails
2222
+ ValueError: If the label is invalid
2223
+ """
2224
+ if not label :
2225
+ raise ValueError ("Label cannot be empty" )
2226
+
2227
+ endpoint = self .get_endpoint ("custom_content_labels" , id = custom_content_id )
2228
+ params = {"name" : label , "prefix" : prefix }
2229
+
2230
+ try :
2231
+ self .delete (endpoint , params = params )
2232
+ return True
2233
+ except Exception as e :
2234
+ log .error (f"Failed to delete label '{ label } ' from custom content { custom_content_id } : { e } " )
2235
+ raise
2236
+
2237
+ def get_custom_content_labels (
2238
+ self , custom_content_id : str , prefix : Optional [str ] = None , cursor : Optional [str ] = None ,
2239
+ sort : Optional [str ] = None , limit : int = 25
2240
+ ) -> List [Dict [str , Any ]]:
2241
+ """
2242
+ Returns all labels for custom content.
2243
+
2244
+ Args:
2245
+ custom_content_id: The ID of the custom content
2246
+ prefix: (optional) Filter the results to labels with a specific prefix
2247
+ cursor: (optional) Cursor for pagination
2248
+ sort: (optional) Sort order for the results. Valid values: 'name', '-name'
2249
+ limit: (optional) Maximum number of labels to return per request. Default: 25
2250
+
2251
+ Returns:
2252
+ List of label objects
2253
+
2254
+ Raises:
2255
+ HTTPError: If the API call fails
2256
+ """
2257
+ endpoint = self .get_endpoint ("custom_content_labels" , id = custom_content_id )
2258
+ params = {"limit" : limit }
2259
+
2260
+ if prefix :
2261
+ params ["prefix" ] = prefix
2161
2262
2162
2263
if cursor :
2163
2264
params ["cursor" ] = cursor
2164
2265
2266
+ if sort :
2267
+ if sort not in ("name" , "-name" ):
2268
+ raise ValueError ("Sort must be one of 'name', '-name'" )
2269
+ params ["sort" ] = sort
2270
+
2165
2271
try :
2166
2272
return list (self ._get_paged (endpoint , params = params ))
2167
2273
except Exception as e :
2168
- log .error (f"Failed to retrieve content property settings: { e } " )
2274
+ log .error (f"Failed to retrieve labels for custom content { custom_content_id } : { e } " )
2275
+ raise
2276
+
2277
+ def create_custom_content_property (self , custom_content_id : str , key : str , value : Any ) -> Dict [str , Any ]:
2278
+ """
2279
+ Creates a new property for custom content.
2280
+
2281
+ Args:
2282
+ custom_content_id: The ID of the custom content
2283
+ key: The key of the property to create. Must only contain alphanumeric
2284
+ characters, periods, and hyphens
2285
+ value: The value of the property. Can be any JSON-serializable value
2286
+
2287
+ Returns:
2288
+ The created property object
2289
+
2290
+ Raises:
2291
+ HTTPError: If the API call fails
2292
+ ValueError: If the key has invalid characters
2293
+ """
2294
+ # Validate key format
2295
+ if not re .match (r"^[a-zA-Z0-9.\-]+$" , key ):
2296
+ raise ValueError ("Property key must only contain alphanumeric characters, periods, and hyphens." )
2297
+
2298
+ endpoint = self .get_endpoint ("custom_content_properties" , id = custom_content_id )
2299
+
2300
+ data = {"key" : key , "value" : value }
2301
+
2302
+ try :
2303
+ return self .post (endpoint , data = data )
2304
+ except Exception as e :
2305
+ log .error (f"Failed to create property { key } for custom content { custom_content_id } : { e } " )
2306
+ raise
2307
+
2308
+ def update_custom_content_property (
2309
+ self , custom_content_id : str , key : str , value : Any , version_number : int , version_message : str = ""
2310
+ ) -> Dict [str , Any ]:
2311
+ """
2312
+ Updates an existing property for custom content.
2313
+
2314
+ Args:
2315
+ custom_content_id: The ID of the custom content
2316
+ key: The key of the property to update
2317
+ value: The new value of the property. Can be any JSON-serializable value
2318
+ version_number: The version number for concurrency control
2319
+ version_message: (optional) A message describing the change
2320
+
2321
+ Returns:
2322
+ The updated property object
2323
+
2324
+ Raises:
2325
+ HTTPError: If the API call fails
2326
+ """
2327
+ endpoint = self .get_endpoint ("custom_content_property_by_key" , id = custom_content_id , key = key )
2328
+
2329
+ data = {
2330
+ "key" : key ,
2331
+ "value" : value ,
2332
+ "version" : {"number" : version_number , "message" : version_message },
2333
+ }
2334
+
2335
+ try :
2336
+ return self .put (endpoint , data = data )
2337
+ except Exception as e :
2338
+ log .error (f"Failed to update property { key } for custom content { custom_content_id } : { e } " )
2339
+ raise
2340
+
2341
+ def delete_custom_content_property (self , custom_content_id : str , key : str ) -> bool :
2342
+ """
2343
+ Deletes a property from custom content.
2344
+
2345
+ Args:
2346
+ custom_content_id: The ID of the custom content
2347
+ key: The key of the property to delete
2348
+
2349
+ Returns:
2350
+ True if the property was successfully deleted, False otherwise
2351
+
2352
+ Raises:
2353
+ HTTPError: If the API call fails
2354
+ """
2355
+ endpoint = self .get_endpoint ("custom_content_property_by_key" , id = custom_content_id , key = key )
2356
+
2357
+ try :
2358
+ self .delete (endpoint )
2359
+ return True
2360
+ except Exception as e :
2361
+ log .error (f"Failed to delete property { key } for custom content { custom_content_id } : { e } " )
2169
2362
raise
0 commit comments