66]
77
88
9- from typing import Any , Generic , List , Optional , Sequence , TypeVar , cast
9+ from typing import Any , Generic , List , Literal , Optional , Sequence , TypeVar , cast
1010
1111from arangoasync .cursor import Cursor
1212from arangoasync .errno import (
2626 DocumentReplaceError ,
2727 DocumentRevisionError ,
2828 DocumentUpdateError ,
29+ EdgeListError ,
2930 IndexCreateError ,
3031 IndexDeleteError ,
3132 IndexGetError ,
@@ -111,11 +112,13 @@ def _validate_id(self, doc_id: str) -> str:
111112 raise DocumentParseError (f'Bad collection name in document ID "{ doc_id } "' )
112113 return doc_id
113114
114- def _extract_id (self , body : Json ) -> str :
115+ def _extract_id (self , body : Json , validate : bool = True ) -> str :
115116 """Extract the document ID from document body.
116117
117118 Args:
118119 body (dict): Document body.
120+ validate (bool): Whether to validate the document ID,
121+ checking if it belongs to the current collection.
119122
120123 Returns:
121124 str: Document ID.
@@ -125,7 +128,10 @@ def _extract_id(self, body: Json) -> str:
125128 """
126129 try :
127130 if "_id" in body :
128- return self ._validate_id (body ["_id" ])
131+ if validate :
132+ return self ._validate_id (body ["_id" ])
133+ else :
134+ return cast (str , body ["_id" ])
129135 else :
130136 key : str = body ["_key" ]
131137 return self ._id_prefix + key
@@ -150,28 +156,30 @@ def _ensure_key_from_id(self, body: Json) -> Json:
150156 body ["_key" ] = doc_id [len (self ._id_prefix ) :]
151157 return body
152158
153- def _prep_from_doc (self , document : str | Json ) -> str :
159+ def _get_doc_id (self , document : str | Json , validate : bool = True ) -> str :
154160 """Prepare document ID before a query.
155161
156162 Args:
157163 document (str | dict): Document ID, key or body.
164+ validate (bool): Whether to validate the document ID,
165+ checking if it belongs to the current collection.
158166
159167 Returns:
160168 Document ID and request headers.
161169
162170 Raises:
163171 DocumentParseError: On missing ID and key.
164- TypeError: On bad document type.
165172 """
166- if isinstance (document , dict ):
167- doc_id = self ._extract_id (document )
168- elif isinstance (document , str ):
173+ if isinstance (document , str ):
169174 if "/" in document :
170- doc_id = self ._validate_id (document )
175+ if validate :
176+ doc_id = self ._validate_id (document )
177+ else :
178+ doc_id = document
171179 else :
172180 doc_id = self ._id_prefix + document
173181 else :
174- raise TypeError ( "Document must be str or a dict" )
182+ doc_id = self . _extract_id ( document , validate )
175183
176184 return doc_id
177185
@@ -585,7 +593,7 @@ async def has(
585593 References:
586594 - `get-a-document-header <https://docs.arangodb.com/stable/develop/http-api/documents/#get-a-document-header>`__
587595 """ # noqa: E501
588- handle = self ._prep_from_doc (document )
596+ handle = self ._get_doc_id (document )
589597
590598 headers : RequestHeaders = {}
591599 if allow_dirty_read :
@@ -1314,7 +1322,7 @@ async def get(
13141322 References:
13151323 - `get-a-document <https://docs.arangodb.com/stable/develop/http-api/documents/#get-a-document>`__
13161324 """ # noqa: E501
1317- handle = self ._prep_from_doc (document )
1325+ handle = self ._get_doc_id (document )
13181326
13191327 headers : RequestHeaders = {}
13201328 if allow_dirty_read :
@@ -1814,7 +1822,7 @@ async def get(
18141822 References:
18151823 - `get-a-vertex <https://docs.arangodb.com/stable/develop/http-api/graphs/named-graphs/#get-a-vertex>`__
18161824 """ # noqa: E501
1817- handle = self ._prep_from_doc (vertex )
1825+ handle = self ._get_doc_id (vertex )
18181826
18191827 headers : RequestHeaders = {}
18201828 if if_match is not None :
@@ -1958,7 +1966,7 @@ async def update(
19581966 request = Request (
19591967 method = Method .PATCH ,
19601968 endpoint = f"/_api/gharial/{ self ._graph } /vertex/"
1961- f"{ self ._prep_from_doc (cast (Json , vertex ))} " ,
1969+ f"{ self ._get_doc_id (cast (Json , vertex ))} " ,
19621970 params = params ,
19631971 headers = headers ,
19641972 data = self ._doc_serializer .dumps (vertex ),
@@ -2033,7 +2041,7 @@ async def replace(
20332041 request = Request (
20342042 method = Method .PUT ,
20352043 endpoint = f"/_api/gharial/{ self ._graph } /vertex/"
2036- f"{ self ._prep_from_doc (cast (Json , vertex ))} " ,
2044+ f"{ self ._get_doc_id (cast (Json , vertex ))} " ,
20372045 params = params ,
20382046 headers = headers ,
20392047 data = self ._doc_serializer .dumps (vertex ),
@@ -2101,7 +2109,7 @@ async def delete(
21012109 request = Request (
21022110 method = Method .DELETE ,
21032111 endpoint = f"/_api/gharial/{ self ._graph } /vertex/"
2104- f"{ self ._prep_from_doc (cast (Json , vertex ))} " ,
2112+ f"{ self ._get_doc_id (cast (Json , vertex ))} " ,
21052113 params = params ,
21062114 headers = headers ,
21072115 )
@@ -2213,7 +2221,7 @@ async def get(
22132221 References:
22142222 - `get-an-edge <https://docs.arangodb.com/stable/develop/http-api/graphs/named-graphs/#get-an-edge>`__
22152223 """ # noqa: E501
2216- handle = self ._prep_from_doc (edge )
2224+ handle = self ._get_doc_id (edge )
22172225
22182226 headers : RequestHeaders = {}
22192227 if if_match is not None :
@@ -2362,7 +2370,7 @@ async def update(
23622370 request = Request (
23632371 method = Method .PATCH ,
23642372 endpoint = f"/_api/gharial/{ self ._graph } /edge/"
2365- f"{ self ._prep_from_doc (cast (Json , edge ))} " ,
2373+ f"{ self ._get_doc_id (cast (Json , edge ))} " ,
23662374 params = params ,
23672375 headers = headers ,
23682376 data = self ._doc_serializer .dumps (edge ),
@@ -2441,7 +2449,7 @@ async def replace(
24412449 request = Request (
24422450 method = Method .PUT ,
24432451 endpoint = f"/_api/gharial/{ self ._graph } /edge/"
2444- f"{ self ._prep_from_doc (cast (Json , edge ))} " ,
2452+ f"{ self ._get_doc_id (cast (Json , edge ))} " ,
24452453 params = params ,
24462454 headers = headers ,
24472455 data = self ._doc_serializer .dumps (edge ),
@@ -2512,7 +2520,7 @@ async def delete(
25122520 request = Request (
25132521 method = Method .DELETE ,
25142522 endpoint = f"/_api/gharial/{ self ._graph } /edge/"
2515- f"{ self ._prep_from_doc (cast (Json , edge ))} " ,
2523+ f"{ self ._get_doc_id (cast (Json , edge ))} " ,
25162524 params = params ,
25172525 headers = headers ,
25182526 )
@@ -2536,3 +2544,93 @@ def response_handler(resp: Response) -> bool | Json:
25362544 raise DocumentDeleteError (resp , request , msg )
25372545
25382546 return await self ._executor .execute (request , response_handler )
2547+
2548+ async def edges (
2549+ self ,
2550+ vertex : str | Json ,
2551+ direction : Optional [Literal ["in" , "out" ]] = None ,
2552+ allow_dirty_read : Optional [bool ] = None ,
2553+ ) -> Result [Json ]:
2554+ """Return the edges starting or ending at the specified vertex.
2555+
2556+ Args:
2557+ vertex (str | dict): Document ID, key or body.
2558+ direction (str | None): Direction of the edges to return. Selects `in`
2559+ or `out` direction for edges. If not set, any edges are returned.
2560+ allow_dirty_read (bool | None): Allow reads from followers in a cluster.
2561+
2562+ Returns:
2563+ dict: List of edges and statistics.
2564+
2565+ Raises:
2566+ EdgeListError: If retrieval fails.
2567+
2568+ References:
2569+ - `get-inbound-and-outbound-edges <https://docs.arangodb.com/stable/develop/http-api/graphs/edges/#get-inbound-and-outbound-edges>`__
2570+ """ # noqa: E501
2571+ params : Params = {
2572+ "vertex" : self ._get_doc_id (vertex , validate = False ),
2573+ }
2574+ if direction is not None :
2575+ params ["direction" ] = direction
2576+
2577+ headers : RequestHeaders = {}
2578+ if allow_dirty_read is not None :
2579+ headers ["x-arango-allow-dirty-read" ] = "true" if allow_dirty_read else False
2580+
2581+ request = Request (
2582+ method = Method .GET ,
2583+ endpoint = f"/_api/edges/{ self ._name } " ,
2584+ params = params ,
2585+ headers = headers ,
2586+ )
2587+
2588+ def response_handler (resp : Response ) -> Json :
2589+ if not resp .is_success :
2590+ raise EdgeListError (resp , request )
2591+ body = self .deserializer .loads (resp .raw_body )
2592+ for key in ("error" , "code" ):
2593+ body .pop (key )
2594+ return body
2595+
2596+ return await self ._executor .execute (request , response_handler )
2597+
2598+ async def link (
2599+ self ,
2600+ from_vertex : str | Json ,
2601+ to_vertex : str | Json ,
2602+ data : Optional [Json ] = None ,
2603+ wait_for_sync : Optional [bool ] = None ,
2604+ return_new : bool = False ,
2605+ ) -> Result [Json ]:
2606+ """Insert a new edge document linking the given vertices.
2607+
2608+ Args:
2609+ from_vertex (str | dict): "_from" vertex document ID or body with "_id"
2610+ field.
2611+ to_vertex (str | dict): "_to" vertex document ID or body with "_id" field.
2612+ data (dict | None): Any extra data for the new edge document. If it has
2613+ "_key" or "_id" field, its value is used as key of the new edge document
2614+ (otherwise it is auto-generated).
2615+ wait_for_sync (bool | None): Wait until operation has been synced to disk.
2616+ return_new: Optional[bool]: Additionally return the complete new document
2617+ under the attribute `new` in the result.
2618+
2619+ Returns:
2620+ dict: Document metadata (e.g. document id, key, revision).
2621+ If `return_new` is specified, the result contains the document
2622+ metadata in the "edge" field and the new document in the "new" field.
2623+
2624+ Raises:
2625+ DocumentInsertError: If insertion fails.
2626+ DocumentParseError: If the document is malformed.
2627+ """
2628+ edge : Json = {
2629+ "_from" : self ._get_doc_id (from_vertex , validate = False ),
2630+ "_to" : self ._get_doc_id (to_vertex , validate = False ),
2631+ }
2632+ if data is not None :
2633+ edge .update (self ._ensure_key_from_id (data ))
2634+ return await self .insert (
2635+ cast (T , edge ), wait_for_sync = wait_for_sync , return_new = return_new
2636+ )
0 commit comments