44"""
55Confluence Cloud API implementation
66"""
7+ import functools
8+ import json
79import logging
10+ import re
811import warnings
912from typing import Any , Dict , List , Optional , Tuple , Union
1013
@@ -31,6 +34,14 @@ def __init__(self, url: str, *args, **kwargs):
3134 kwargs .setdefault ("api_version" , 2 )
3235 super ().__init__ (url , * args , ** kwargs )
3336
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+
3445 # Warn about V1 method usage
3546 warnings .warn (
3647 "V1 methods are deprecated in ConfluenceCloud. Use V2 methods instead." , DeprecationWarning , stacklevel = 2
@@ -49,7 +60,7 @@ def __getattr__(self, name):
4960 Raises:
5061 AttributeError: If no mapping exists and the attribute isn't found
5162 """
52- if name in self ._compatibility_method_mapping :
63+ if hasattr ( self , "_compatibility_method_mapping" ) and name in self ._compatibility_method_mapping :
5364 v2_method_name = self ._compatibility_method_mapping [name ]
5465 v2_method = getattr (self , v2_method_name )
5566
@@ -840,37 +851,35 @@ def get_page_property_by_key(self, page_id: str, property_key: str) -> Dict[str,
840851 log .error (f"Failed to retrieve property { property_key } for page { page_id } : { e } " )
841852 raise
842853
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 ]:
844855 """
845856 Creates a new property for a page.
846857
847858 Args:
848859 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
852863
853864 Returns:
854- The created page property object
865+ The created property object
855866
856867 Raises:
857868 HTTPError: If the API call fails
858- ValueError: If the property_key has invalid characters
869+ ValueError: If the key has invalid characters
859870 """
860871 # 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 ):
864873 raise ValueError ("Property key must only contain alphanumeric characters and periods." )
865874
866875 endpoint = self .get_endpoint ("page_properties" , id = page_id )
867876
868- data = {"key" : property_key , "value" : property_value }
877+ data = {"key" : key , "value" : value }
869878
870879 try :
871880 return self .post (endpoint , data = data )
872881 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 } " )
874883 raise
875884
876885 def update_page_property (
@@ -2121,7 +2130,7 @@ def get_custom_content(
21212130 page_id: (optional) Filter by page ID
21222131 blog_post_id: (optional) Filter by blog post ID
21232132 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
21252134 status: (optional) Filter by status. Valid values: "current", "draft", "archived", "trashed", "deleted", "any"
21262135 body_format: (optional) Format to retrieve the body in.
21272136 Valid values: "storage", "atlas_doc_format", "raw", "view"
@@ -2151,19 +2160,203 @@ def get_custom_content(
21512160 if ids :
21522161 params ["id" ] = "," .join (ids )
21532162 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
21552172
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
21582178
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
21612262
21622263 if cursor :
21632264 params ["cursor" ] = cursor
21642265
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+
21652271 try :
21662272 return list (self ._get_paged (endpoint , params = params ))
21672273 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 } " )
21692362 raise
0 commit comments