Skip to content

Initial commit #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Feb 2, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Update sdk
  • Loading branch information
1pxone committed Jan 30, 2025
commit 334d1cef3462004de80b14c54d367278600c9e31
11 changes: 6 additions & 5 deletions src/rushdb/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
"""

from .client import RushDBClient
from .common import RushDBError, RelationOptions, RelationDetachOptions
from .record import Record
from .transaction import Transaction
from .property import Property
from .common import RushDBError
from .models.relationship import RelationshipOptions, RelationshipDetachOptions
from .models.property import Property
from .models.record import Record
from .models.transaction import Transaction

__all__ = ['RushDBClient', 'RushDBError', 'Record', 'RelationOptions', 'RelationDetachOptions', 'Transaction', 'Property']
__all__ = ['RushDBClient', 'RushDBError', 'Record', 'Transaction', 'Property', 'RelationshipOptions', 'RelationshipDetachOptions']
Empty file added src/rushdb/api/__init__.py
Empty file.
9 changes: 9 additions & 0 deletions src/rushdb/api/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from typing import TYPE_CHECKING

if TYPE_CHECKING:
from ..client import RushDBClient

class BaseAPI:
"""Base class for all API endpoints."""
def __init__(self, client: 'RushDBClient'):
self.client = client
14 changes: 14 additions & 0 deletions src/rushdb/api/labels.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from typing import List, Optional

from .base import BaseAPI
from ..models.search_query import SearchQuery
from ..models.transaction import Transaction


class LabelsAPI(BaseAPI):
"""API for managing labels in RushDB."""
def list(self, query: Optional[SearchQuery] = None, transaction: Optional[Transaction] = None) -> List[str]:
"""List all labels."""
headers = Transaction._build_transaction_header(transaction.id if transaction else None)

return self.client._make_request('POST', '/api/v1/labels', data=query or {}, headers=headers)
33 changes: 33 additions & 0 deletions src/rushdb/api/properties.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from typing import List, Optional, Literal

from .base import BaseAPI
from ..models.property import Property, PropertyValuesData
from ..models.search_query import SearchQuery
from ..models.transaction import Transaction


class PropertiesAPI(BaseAPI):
"""API for managing properties in RushDB."""
def find(self, query: Optional[SearchQuery] = None, transaction: Optional[Transaction] = None) -> List[Property]:
"""List all properties."""
headers = Transaction._build_transaction_header(transaction.id if transaction else None)

return self.client._make_request('POST', '/api/v1/properties', query or {}, headers)

def find_by_id(self, property_id: str, transaction: Optional[Transaction] = None) -> Property:
"""Get a property by ID."""
headers = Transaction._build_transaction_header(transaction.id if transaction else None)

return self.client._make_request('GET', f'/api/v1/properties/{property_id}', headers=headers)

def delete(self, property_id: str, transaction: Optional[Transaction] = None) -> None:
"""Delete a property."""
headers = Transaction._build_transaction_header(transaction.id if transaction else None)

return self.client._make_request('DELETE', f'/api/v1/properties/{property_id}', headers=headers)

def values(self, property_id: str, sort: Optional[Literal['asc', 'desc']], skip: Optional[int], limit: Optional[int], transaction: Optional[Transaction] = None) -> PropertyValuesData:
"""Get values data for a property."""
headers = Transaction._build_transaction_header(transaction.id if transaction else None)

return self.client._make_request('GET', f'/api/v1/properties/{property_id}/values', headers=headers, params={ "sort": sort, "skip": skip, "limit": limit })
64 changes: 20 additions & 44 deletions src/rushdb/records_api.py → src/rushdb/api/records.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
from typing import Dict, Any, Optional, Union, List

from src.rushdb import RushDBClient, RushDBError
from src.rushdb.transaction import Transaction
from src.rushdb.common import RelationOptions, RelationDetachOptions
from src.rushdb.record import Record
from .base import BaseAPI
from ..common import RushDBError
from ..models.relationship import RelationshipOptions, RelationshipDetachOptions
from ..models.search_query import SearchQuery
from ..models.transaction import Transaction
from ..models.record import Record


class RecordsAPI:
class RecordsAPI(BaseAPI):
"""API for managing records in RushDB."""
def __init__(self, client: 'RushDBClient'):
self.client = client

def set(self, record_id: str, data: Dict[str, Any], transaction: Optional[Transaction] = None) -> Dict[str, str]:
"""Update a record by ID."""
headers = Transaction._build_transaction_header(transaction.id if transaction else None)
Expand Down Expand Up @@ -45,7 +44,7 @@ def create(self, label: str, data: Dict[str, Any], options: Optional[Dict[str, b
}
}
response = self.client._make_request('POST', '/api/v1/records', payload, headers)
return Record(self.client, response)
return Record(self.client, response.get('data'))

def create_many(self, label: str, data: Union[Dict[str, Any], List[Dict[str, Any]]], options: Optional[Dict[str, bool]] = None, transaction: Optional[Transaction] = None) -> List[Record]:
"""Create multiple records.
Expand All @@ -70,23 +69,19 @@ def create_many(self, label: str, data: Union[Dict[str, Any], List[Dict[str, Any
}
}
response = self.client._make_request('POST', '/api/v1/records/import/json', payload, headers)
return [Record(self.client, record) for record in response.get('data')]

print('r:', response)

return [Record(self.client, {"data": record}) for record in response.get('data')]

def attach(self, source: Union[str, Dict[str, Any]], target: Union[str, List[str], Dict[str, Any], List[Dict[str, Any]]], options: Optional[RelationOptions] = None, transaction: Optional[Transaction] = None) -> Dict[str, str]:
def attach(self, source: Union[str, Dict[str, Any]], target: Union[str, List[str], Dict[str, Any], List[Dict[str, Any]]], options: Optional[RelationshipOptions] = None, transaction: Optional[Transaction] = None) -> Dict[str, str]:
"""Attach records to a source record."""
headers = Transaction._build_transaction_header(transaction.id if transaction else None)
source_id = self._extract_target_ids(source)[0]
target_ids = self._extract_target_ids(target)
payload = {'targetIds': target_ids}
if options:
payload.update(options)
print(payload)
return self.client._make_request('POST', f'/api/v1/records/{source_id}/relations', payload, headers)

def detach(self, source: Union[str, Dict[str, Any]], target: Union[str, List[str], Dict[str, Any], List[Dict[str, Any]]], options: Optional[RelationDetachOptions] = None, transaction: Optional[Transaction] = None) -> Dict[str, str]:
def detach(self, source: Union[str, Dict[str, Any]], target: Union[str, List[str], Dict[str, Any], List[Dict[str, Any]]], options: Optional[RelationshipDetachOptions] = None, transaction: Optional[Transaction] = None) -> Dict[str, str]:
"""Detach records from a source record."""
headers = Transaction._build_transaction_header(transaction.id if transaction else None)
source_id = self._extract_target_ids(source)[0]
Expand All @@ -96,7 +91,7 @@ def detach(self, source: Union[str, Dict[str, Any]], target: Union[str, List[str
payload.update(options)
return self.client._make_request('PUT', f'/api/v1/records/{source_id}/relations', payload, headers)

def delete(self, query: Dict[str, Any], transaction: Optional[Transaction] = None) -> Dict[str, str]:
def delete(self, query: SearchQuery, transaction: Optional[Transaction] = None) -> Dict[str, str]:
"""Delete records matching the query."""
headers = Transaction._build_transaction_header(transaction.id if transaction else None)
return self.client._make_request('PUT', '/api/v1/records/delete', query, headers)
Expand All @@ -111,35 +106,16 @@ def delete_by_id(self, id_or_ids: Union[str, List[str]], transaction: Optional[T
}, headers)
return self.client._make_request('DELETE', f'/api/v1/records/{id_or_ids}', None, headers)

def find(self, query: Optional[Dict[str, Any]] = None, record_id: Optional[str] = None, transaction: Optional[Transaction] = None) -> List[Record]:
def find(self, query: Optional[SearchQuery] = None, record_id: Optional[str] = None, transaction: Optional[Transaction] = None) -> List[Record]:
"""Find records matching the query."""
headers = Transaction._build_transaction_header(transaction.id if transaction else None)
path = f'/api/v1/records/{record_id}/search' if record_id else '/api/v1/records/search'
response = self.client._make_request('POST', path, data=query, headers=headers)
return [Record(self.client, record) for record in response]

def find_by_id(self, id_or_ids: Union[str, List[str]], transaction: Optional[Transaction] = None) -> Union[Record, List[Record]]:
"""Find records by ID(s)."""
headers = Transaction._build_transaction_header(transaction.id if transaction else None)
if isinstance(id_or_ids, list):
response = self.client._make_request('POST', '/api/v1/records', {'ids': id_or_ids}, headers)
return [Record(self.client, record) for record in response]
response = self.client._make_request('GET', f'/api/v1/records/{id_or_ids}', None, headers)
return Record(self.client, response)

def find_one(self, query: Dict[str, Any], transaction: Optional[Transaction] = None) -> Optional[Record]:
"""Find a single record matching the query."""
headers = Transaction._build_transaction_header(transaction.id if transaction else None)
query = {**query, 'limit': 1, 'skip': 0}
result = self.client._make_request('POST', '/api/v1/records/search', query, headers)
return Record(self.client, result[0]) if result else None

def find_unique(self, query: Dict[str, Any], transaction: Optional[Transaction] = None) -> Record:
"""Find a unique record matching the query."""
result = self.find_one(query, transaction)
if not result:
raise RushDBError("No records found matching the unique query")
return result
try:
headers = Transaction._build_transaction_header(transaction.id if transaction else None)
path = f'/api/v1/records/{record_id}/search' if record_id else '/api/v1/records/search'
response = self.client._make_request('POST', path, data=query or {}, headers=headers)
return [Record(self.client, record) for record in response.get('data')]
except:
return []

def import_csv(self, label: str, csv_data: Union[str, bytes], options: Optional[Dict[str, bool]] = None, transaction: Optional[Transaction] = None) -> List[Dict[str, Any]]:
"""Import data from CSV."""
Expand Down
58 changes: 58 additions & 0 deletions src/rushdb/api/relationships.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
from typing import List, Optional, TypedDict, Union
from urllib.parse import urlencode

from .base import BaseAPI
from ..models.relationship import Relationship
from ..models.search_query import SearchQuery
from ..models.transaction import Transaction

class PaginationParams(TypedDict, total=False):
"""TypedDict for pagination parameters."""
limit: int
skip: int



class RelationsAPI(BaseAPI):
"""API for managing relationships in RushDB."""

async def find(
self,
query: Optional[SearchQuery] = None,
pagination: Optional[PaginationParams] = None,
transaction: Optional[Union[Transaction, str]] = None
) -> List[Relationship]:
"""Find relations matching the search parameters.

Args:
query: Search query parameters
pagination: Optional pagination parameters (limit and skip)
transaction: Optional transaction context or transaction ID

Returns:
List of matching relations
"""
# Build query string for pagination
query_params = {}
if pagination:
if pagination.get('limit') is not None:
query_params['limit'] = str(pagination['limit'])
if pagination.get('skip') is not None:
query_params['skip'] = str(pagination['skip'])

# Construct path with query string
query_string = f"?{urlencode(query_params)}" if query_params else ""
path = f"/records/relations/search{query_string}"

# Build headers with transaction if present
headers = Transaction._build_transaction_header(transaction.id if transaction else None)

# Make request
response = self.client._make_request(
method='POST',
path=path,
data=query or {},
headers=headers
)

return response.data
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
from typing import Optional

from src.rushdb import RushDBClient
from src.rushdb.transaction import Transaction
from .base import BaseAPI
from ..models.transaction import Transaction


class TransactionsAPI:
class TransactionsAPI(BaseAPI):
"""API for managing transactions in RushDB."""
def __init__(self, client: 'RushDBClient'):
self.client = client

def begin(self, ttl: Optional[int] = None) -> Transaction:
"""Begin a new transaction.

Expand Down
10 changes: 5 additions & 5 deletions src/rushdb/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
import urllib.error
from typing import Any, Dict, Optional

from src.rushdb.common import RushDBError
from src.rushdb.labels_api import LabelsAPI
from src.rushdb.properties_api import PropertiesAPI
from src.rushdb.records_api import RecordsAPI
from src.rushdb.transactions_api import TransactionsAPI
from .common import RushDBError
from .api.labels import LabelsAPI
from .api.properties import PropertiesAPI
from .api.records import RecordsAPI
from .api.transactions import TransactionsAPI

class RushDBClient:
"""Main client for interacting with RushDB."""
Expand Down
14 changes: 1 addition & 13 deletions src/rushdb/common.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,5 @@
from typing import Dict, List, Optional, Union, TypedDict, Literal
from typing import Dict, Optional

# Relation types
RelationDirection = Literal['in', 'out']

class RelationOptions(TypedDict, total=False):
"""Options for creating relations."""
direction: Optional[RelationDirection]
type: Optional[str]

class RelationDetachOptions(TypedDict, total=False):
"""Options for detaching relations."""
direction: Optional[RelationDirection]
typeOrTypes: Optional[Union[str, List[str]]]

class RushDBError(Exception):
"""Custom exception for RushDB client errors."""
Expand Down
21 changes: 0 additions & 21 deletions src/rushdb/labels_api.py

This file was deleted.

Empty file added src/rushdb/models/__init__.py
Empty file.
File renamed without changes.
26 changes: 16 additions & 10 deletions src/rushdb/record.py → src/rushdb/models/record.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,28 @@
from datetime import datetime
from typing import Dict, Any, Optional, Union, List

from src.rushdb import RushDBClient
from src.rushdb.common import RelationOptions, RelationDetachOptions
from src.rushdb.transaction import Transaction
from typing import Dict, Any, Optional, Union, List, TYPE_CHECKING

from .relationship import RelationshipOptions, RelationshipDetachOptions
from .transaction import Transaction
if TYPE_CHECKING:
from ..client import RushDBClient

class Record:
"""Represents a record in RushDB with methods for manipulation."""
def __init__(self, client: 'RushDBClient', data: Dict[str, Any] = None):
self._client = client

self.data = data.get('data')
# Handle different data formats
if isinstance(data, dict):
self.data = data
elif isinstance(data, str):
# If just a string is passed, assume it's an ID
self.data = {}
else:
raise ValueError(f"Invalid data format for Record: {type(data)}")

@property
def id(self) -> str:
"""Get record ID."""
return self.data['__id']
return self.data.get('__id')

@property
def proptypes(self) -> str:
Expand Down Expand Up @@ -48,12 +54,12 @@ def update(self, data: Dict[str, Any], transaction: Optional[Transaction] = None
"""Update record data through API request."""
return self._client.records.update(self.id, data, transaction)

def attach(self, target: Union[str, List[str], Dict[str, Any], List[Dict[str, Any]], 'Record', List['Record']], options: Optional[RelationOptions] = None, transaction: Optional[
def attach(self, target: Union[str, List[str], Dict[str, Any], List[Dict[str, Any]], 'Record', List['Record']], options: Optional[RelationshipOptions] = None, transaction: Optional[
Transaction] = None) -> Dict[str, str]:
"""Attach other records to this record."""
return self._client.records.attach(self.id, target, options, transaction)

def detach(self, target: Union[str, List[str], Dict[str, Any], List[Dict[str, Any]], 'Record', List['Record']], options: Optional[RelationDetachOptions] = None, transaction: Optional[
def detach(self, target: Union[str, List[str], Dict[str, Any], List[Dict[str, Any]], 'Record', List['Record']], options: Optional[RelationshipDetachOptions] = None, transaction: Optional[
Transaction] = None) -> Dict[str, str]:
"""Detach records from this record."""
return self._client.records.detach(self.id, target, options, transaction)
Expand Down
Loading
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy