Skip to content

Commit 9162f4b

Browse files
committed
TypeBridge 1.2.3 - Enhanced FunctionQuery, Driver Injection, and TypeQL Validation
1 parent 1a03922 commit 9162f4b

3 files changed

Lines changed: 210 additions & 2 deletions

File tree

CHANGELOG.md

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,214 @@
22

33
All notable changes to TypeBridge will be documented in this file.
44

5+
## [1.2.3] - 2025-12-28
6+
7+
### New Features
8+
9+
#### Enhanced FunctionQuery System (PR #84)
10+
- **Complete TypeQL query generation for function calls**
11+
- FunctionQuery generates full `match let` queries with variable binding
12+
- Support for scalar returns, stream returns, and composite tuples
13+
- Query methods: `to_call()`, `to_match_let()`, `to_fetch()`, `to_query()`
14+
- Pagination support with limit/offset/sort
15+
- Location: `type_bridge/expressions/functions.py`
16+
17+
**Usage Example:**
18+
```python
19+
from myschema.functions import count_artifacts, get_neighbor_ids
20+
21+
# Simple count
22+
fn = count_artifacts()
23+
query = fn.to_query()
24+
# → match let $integer = count-artifacts(); fetch { "integer": $integer };
25+
26+
# Stream with pagination
27+
fn = get_neighbor_ids(target_id="abc-123")
28+
query = fn.to_query(limit=10, offset=5)
29+
```
30+
31+
#### Driver Injection Support (PR #86)
32+
- **Share TypeDB driver instances across Database objects**
33+
- Optional `driver` parameter in `Database.__init__()`
34+
- Ownership tracking with `_owns_driver` flag for lifecycle control
35+
- Enables connection pooling and framework integration
36+
- Location: `type_bridge/session.py`
37+
38+
**Benefits:**
39+
- Resource efficiency (share one TCP connection)
40+
- Application-level connection pooling strategies
41+
- Centralized driver lifecycle management
42+
- Backwards compatible (default behavior unchanged)
43+
44+
**Usage Example:**
45+
```python
46+
driver = TypeDB.driver("localhost:1729", Credentials("admin", "password"))
47+
48+
db1 = Database(database="project_a", driver=driver) # Shares driver
49+
db2 = Database(database="project_b", driver=driver) # Shares driver
50+
51+
db1.close() # Just clears reference
52+
db2.close() # Just clears reference
53+
driver.close() # Actually closes connection
54+
```
55+
56+
#### @independent Annotation Support (PR #83)
57+
- **Standalone attributes without entity/relation owners**
58+
- Add `independent = True` ClassVar to attribute classes
59+
- Generates `@independent` annotation in TypeQL schema
60+
- Enables standalone attribute insertion and queries
61+
- Location: `type_bridge/attribute/base.py`
62+
63+
**Usage Example:**
64+
```python
65+
class Language(String):
66+
"""Can exist without an owner."""
67+
independent = True
68+
69+
# Generated TypeQL: attribute Language @independent, value string;
70+
```
71+
72+
#### @range Validation and Schema Generation (PR #82)
73+
- **Runtime validation with database enforcement**
74+
- `Integer` and `Double` validate `range_constraint` ClassVar at initialization
75+
- Schema generation includes `@range(min..max)` annotations
76+
- Also generates `@regex` and `@values` annotations from ClassVars
77+
- Two-layer validation: Python-side (fail-fast) + TypeDB-side (enforcement)
78+
- Location: `type_bridge/attribute/integer.py`, `type_bridge/attribute/double.py`
79+
80+
**Usage Example:**
81+
```python
82+
from typing import ClassVar
83+
84+
class Age(Integer):
85+
range_constraint: ClassVar[tuple[str | None, str | None]] = ("0", "150")
86+
87+
Age(200) # Raises: ValueError: Age value 200 is above maximum 150
88+
89+
# Generated schema: attribute Age, value integer @range(0..150);
90+
```
91+
92+
#### Batch IID Filtering (PR #81)
93+
- **Django-style `iid__in` lookup for efficient batch queries**
94+
- Filter entities/relations by multiple IIDs in single query
95+
- Role player filtering: `employee__iid__in=[...]`
96+
- Uses flat BooleanExpr to avoid stack overflow with many IIDs
97+
- Location: `type_bridge/expressions/iid.py`, `type_bridge/crud/entity/manager.py`
98+
99+
**Usage Example:**
100+
```python
101+
# Fetch multiple entities by IID
102+
persons = Person.manager(db).filter(iid__in=["0x1a2b3c", "0x4d5e6f"]).execute()
103+
104+
# Filter relations by role player IIDs
105+
employments = Employment.manager(db).filter(employee__iid__in=["0x1a2b3c"]).execute()
106+
```
107+
108+
**Performance:** O(1) query vs O(N) `get_by_iid()` calls.
109+
110+
#### TypeQL Annotation Validation (PR #86)
111+
- **Comprehensive validation for schema annotations**
112+
- `@card`: Validates min ≤ max, non-negative values, detects comma syntax
113+
- `@regex`: Validates patterns compile as valid regex
114+
- `@values`: Validates at least one value, detects duplicates
115+
- `@range`: Validates proper `..` syntax, rejects comma/single-value
116+
- Clear, actionable error messages
117+
- Location: `type_bridge/generator/parser.py`
118+
119+
### Bug Fixes
120+
121+
#### Code Generator Fixes (PR #86)
122+
- **Fixed relation inheritance to include keys, uniques, and cardinalities**
123+
- Child relations now inherit `@key`, `@unique`, and `@card` from parent
124+
- Ensures complete type definitions in generated code
125+
- Location: `type_bridge/generator/render/relations.py`
126+
127+
- **Fixed optional relation attributes in generated models**
128+
- Correct type hints with `| None` for optional fields
129+
- Proper default values (e.g., `timestamp: Timestamp | None = None`)
130+
- Respects cardinality: `@card(1)` = required, no annotation = optional
131+
- Location: `type_bridge/generator/render/relations.py`
132+
133+
- **Fixed Python literal rendering for @range annotations**
134+
- Range values output as numeric literals: `(1, None)` not `("1", null)`
135+
- Fixed type hint from `str | None` to `int | float | None`
136+
- Location: `type_bridge/generator/render/attributes.py`
137+
138+
#### Query Generation Fixes (PR #84)
139+
- **Fixed composite variable lists in FunctionQuery**
140+
- Removed incorrect parentheses around variable lists
141+
- Correct: `match let $a, $b in func()`
142+
- Incorrect (previous): `match let ($a, $b) in func()`
143+
- Location: `type_bridge/expressions/functions.py`
144+
145+
#### Type Checking Fixes
146+
- **Proper type annotations for ty type checker**
147+
- Use `type[Attribute]` instead of generic type
148+
- Use `type[Entity] | type[Relation]` for model params
149+
- Core library passes ty with zero warnings
150+
- Location: `type_bridge/crud/relation/lookup.py`, `type_bridge/schema/introspection.py`
151+
152+
- **Added None checks for optional attributes**
153+
- `assert position is not None` guards before accessing `.value`
154+
- Fixes pyright errors in tests
155+
- Location: `tests/integration/crud/test_iid_feature.py`
156+
157+
### Development & Tooling
158+
159+
#### Project Restructuring
160+
- **Moved Python package to repository root**
161+
- Transitioned from monorepo (`packages/python/`) to root-level package
162+
- TypeScript split into separate [type-bridge-ts](https://github.com/ds1sqe/type-bridge-ts) repository
163+
- Simplified CI/CD configuration
164+
165+
#### Pre-commit Hooks
166+
- **Comprehensive code quality automation**
167+
- ruff linting and formatting
168+
- pyright type checking
169+
- ty type checker for enhanced type safety
170+
- Location: `.pre-commit-config.yaml`
171+
172+
#### Type Checker Configuration
173+
- **Configured ty rules for metaclass compatibility**
174+
- Overrides for tests/examples to handle metaclass-generated code
175+
- Rules: unknown-argument, unresolved-attribute, call-non-callable
176+
- Location: `pyproject.toml` [tool.ty.overrides]
177+
178+
### Documentation
179+
180+
- **FunctionQuery documentation and integration tests**
181+
- Comprehensive examples of query generation patterns
182+
- All function patterns tested (scalar, stream, composite)
183+
184+
- **Database driver injection guide**
185+
- Connection pooling examples
186+
- Framework integration patterns
187+
188+
- **Generator relation cardinality documentation**
189+
- Clarified `@card` behavior on relation attributes
190+
- Required vs optional attribute patterns
191+
192+
### Testing
193+
194+
- **1096 unit tests passing** (100% pass rate)
195+
- **All integration tests passing**
196+
- **0 errors with pyright and ty type checkers**
197+
198+
### Key Files Modified
199+
200+
- `type_bridge/expressions/functions.py` - Enhanced FunctionQuery
201+
- `type_bridge/session.py` - Driver injection support
202+
- `type_bridge/generator/parser.py` - Annotation validation
203+
- `type_bridge/generator/render/relations.py` - Inheritance and optional attributes
204+
- `type_bridge/generator/render/attributes.py` - Python literal rendering
205+
- `type_bridge/crud/relation/lookup.py` - Type annotations
206+
- `type_bridge/schema/introspection.py` - Type annotations
207+
- `type_bridge/attribute/base.py` - @independent support
208+
- `type_bridge/attribute/integer.py` - @range validation
209+
- `type_bridge/attribute/double.py` - @range validation
210+
- `.pre-commit-config.yaml` - Pre-commit hooks configuration
211+
- `pyproject.toml` - ty type checker configuration
212+
5213
## [1.2.2] - 2025-12-25
6214

7215
### Bug Fixes

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
44

55
[project]
66
name = "type-bridge"
7-
version = "1.2.2"
7+
version = "1.2.3"
88
description = "A modern, Pythonic ORM for TypeDB with an Attribute-based API"
99
readme = "README.md"
1010
requires-python = ">=3.13"

type_bridge/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
from type_bridge.session import Connection, Database, TransactionContext
4747
from type_bridge.typedb_driver import Credentials, TransactionType, TypeDB
4848

49-
__version__ = "1.2.2"
49+
__version__ = "1.2.3"
5050

5151
__all__ = [
5252
# Database and session

0 commit comments

Comments
 (0)