Skip to content

Commit bf09b41

Browse files
authored
Update README.md
1 parent 87e648d commit bf09b41

File tree

1 file changed

+1
-223
lines changed

1 file changed

+1
-223
lines changed

README.md

Lines changed: 1 addition & 223 deletions
Original file line numberDiff line numberDiff line change
@@ -253,227 +253,5 @@ pytest tests/django/ # Auto-isolated
253253

254254
---
255255

256-
<<<<<<< HEAD
257-
# Custom configuration
258-
config = PGliteConfig(
259-
timeout=30,
260-
cleanup_on_exit=True,
261-
log_level="DEBUG"
262-
)
263-
264-
# Manual management
265-
with PGliteManager(config) as manager:
266-
engine = manager.get_engine()
267-
SQLModel.metadata.create_all(engine)
268-
269-
with Session(engine) as session:
270-
# Your database operations here
271-
pass
272-
```
273-
274-
## 🔧 Features
275-
276-
### Pytest Fixtures
277-
278-
- **`pglite_engine`**: SQLAlchemy engine connected to PGlite
279-
- **`pglite_session`**: Database session with automatic cleanup
280-
- **`pglite_manager`**: Direct access to PGlite process management
281-
282-
### Automatic Management
283-
284-
- ✅ Process lifecycle management
285-
- ✅ Socket cleanup and health checks
286-
- ✅ Graceful shutdown and error handling
287-
- ✅ Per-test isolation with automatic cleanup
288-
- ✅ Node.js dependency management
289-
290-
### Configuration
291-
292-
```python
293-
from py_pglite import PGliteConfig
294-
295-
config = PGliteConfig(
296-
timeout=30, # Startup timeout in seconds
297-
cleanup_on_exit=True, # Auto cleanup on exit
298-
log_level="INFO", # Logging level (DEBUG/INFO/WARNING/ERROR)
299-
socket_path="/tmp/.s.PGSQL.5432", # Custom socket path
300-
work_dir=None, # Working directory (None = temp dir)
301-
node_modules_check=True, # Verify node_modules exists
302-
auto_install_deps=True, # Auto-install npm dependencies
303-
)
304-
```
305-
306-
### Utility Functions
307-
308-
```python
309-
from py_pglite import utils
310-
311-
# Database cleanup utilities
312-
utils.clean_database_data(engine) # Clean all data
313-
utils.clean_database_data(engine, exclude_tables=["users"]) # Exclude tables
314-
utils.reset_sequences(engine) # Reset auto-increment sequences
315-
utils.verify_database_empty(engine) # Check if database is empty
316-
317-
# Schema operations
318-
utils.create_test_schema(engine, "test_schema") # Create test schema
319-
utils.drop_test_schema(engine, "test_schema") # Drop test schema
320-
321-
# Get table statistics
322-
row_counts = utils.get_table_row_counts(engine) # Dict of table row counts
323-
```
324-
325-
## 📚 Examples
326-
327-
### FastAPI Integration
328-
329-
```python
330-
from fastapi import Depends, FastAPI
331-
from fastapi.testclient import TestClient
332-
from sqlmodel import Session
333-
from py_pglite import pglite_engine
334-
335-
app = FastAPI()
336-
337-
def get_db():
338-
# Production database dependency
339-
pass
340-
341-
@app.post("/users/")
342-
def create_user(user_data: dict, db: Session = Depends(get_db)):
343-
# Your endpoint logic
344-
pass
345-
346-
# Test with PGlite
347-
def test_create_user_endpoint(pglite_engine):
348-
# Override database dependency
349-
def override_get_db():
350-
with Session(pglite_engine) as session:
351-
yield session
352-
353-
app.dependency_overrides[get_db] = override_get_db
354-
355-
with TestClient(app) as client:
356-
response = client.post("/users/", json={"name": "Bob"})
357-
assert response.status_code == 200
358-
```
359-
360-
See also [examples/test_fastapi_auth_example.py](examples/test_fastapi_auth_example.py) for an example of how to use py-pglite with FastAPI e2e test that includes authentication.
361-
362-
### Complex Testing Scenario
363-
364-
```python
365-
def test_complex_operations(pglite_session: Session):
366-
# Create related data
367-
user = User(name="Alice", email="alice@example.com")
368-
pglite_session.add(user)
369-
pglite_session.commit()
370-
pglite_session.refresh(user)
371-
372-
# Create dependent records
373-
orders = [
374-
Order(user_id=user.id, amount=100.0),
375-
Order(user_id=user.id, amount=250.0),
376-
]
377-
pglite_session.add_all(orders)
378-
pglite_session.commit()
379-
380-
# Complex query with joins
381-
result = pglite_session.exec(
382-
select(User.name, func.sum(Order.amount))
383-
.join(Order)
384-
.group_by(User.name)
385-
).first()
386-
387-
assert result[0] == "Alice"
388-
assert result[1] == 350.0
389-
```
390-
391-
## 🤝 Contributing
392-
393-
Contributions welcome! Please read our [Contributing Guide](CONTRIBUTING.md).
394-
395-
1. Fork the repository
396-
2. Create a feature branch
397-
3. Make your changes
398-
4. Add tests for new functionality
399-
5. Run the development workflow: `python hacking.py` | `uv run hacking.py` | `pdm run hacking.py`
400-
6. Submit a pull request
401-
402-
## 📄 License
403-
404-
Apache 2.0 License - see [LICENSE](LICENSE) file.
405-
406-
## 🙏 Acknowledgments
407-
408-
- [PGlite](https://github.com/electric-sql/pglite) - The amazing in-memory PostgreSQL
409-
- [SQLAlchemy](https://www.sqlalchemy.org/) - Python SQL toolkit
410-
- [SQLModel](https://sqlmodel.tiangolo.com/) - Modern Python SQL toolkit
411-
- [Pytest](https://pytest.org/) - Testing framework
412-
413-
## Best Practices
414-
415-
### Multiple Database Sessions
416-
417-
For multiple database connections, use **multiple sessions with the same engine** rather than multiple engines:
418-
419-
```python
420-
# ✅ Recommended: Multiple sessions with same engine
421-
with PGliteManager() as manager:
422-
engine = manager.get_engine()
423-
424-
# Multiple sessions work perfectly
425-
session1 = Session(engine)
426-
session2 = Session(engine)
427-
session3 = Session(engine)
428-
429-
# ❌ Not recommended: Multiple engines from same manager
430-
with PGliteManager() as manager:
431-
engine1 = manager.get_engine() # Can cause connection conflicts
432-
engine2 = manager.get_engine() # when used simultaneously
433-
```
434-
435-
**Why?** Creating multiple SQLAlchemy engines from the same PGlite manager can cause connection pool conflicts since they all connect to the same Unix socket.
436-
437-
### Performance Tips
438-
439-
- Use `pglite_session` fixture for automatic cleanup between tests
440-
- Use `pglite_engine` fixture when you need direct engine access
441-
- Use utility functions for efficient database operations
442-
- Consider custom configurations for specific test requirements
443-
444-
### Testing Patterns
445-
446-
```python
447-
# Pattern 1: Simple CRUD testing
448-
def test_user_crud(pglite_session):
449-
# Create
450-
user = User(name="Test", email="test@example.com")
451-
pglite_session.add(user)
452-
pglite_session.commit()
453-
454-
# Read
455-
found_user = pglite_session.get(User, user.id)
456-
assert found_user.name == "Test"
457-
458-
# Update
459-
found_user.name = "Updated"
460-
pglite_session.commit()
461-
462-
# Delete
463-
pglite_session.delete(found_user)
464-
pglite_session.commit()
465-
466-
# Pattern 2: Custom cleanup
467-
def test_with_custom_cleanup(pglite_engine):
468-
SQLModel.metadata.create_all(pglite_engine)
469-
470-
with Session(pglite_engine) as session:
471-
# Your test logic
472-
pass
473-
474-
# Custom cleanup if needed
475-
utils.clean_database_data(pglite_engine)
476-
```
477-
=======
478256
*py-pglite: Because testing should be simple.*
479-
>>>>>>> 7555fb5 (feat & refactor: decouple sqlalchemy, introduce django & pytest-django)
257+

0 commit comments

Comments
 (0)