Skip to content

Commit a274274

Browse files
Merge pull request #51 from goldlabelapps/staging
This pull request focuses on improving project documentation, updating versioning, enhancing test coverage, and adding a utility script for database maintenance.
2 parents fe65b71 + 77585e5 commit a274274

6 files changed

Lines changed: 136 additions & 65 deletions

File tree

README.md

Lines changed: 85 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,119 @@
1-
## ![Python](/app/static/repoicon.png) Python
1+
## Python FastAPI/Postgres App
22

3-
> With FastAPI using Postgres & tsvector.
3+
**Production-ready, open-source FastAPI application with PostgreSQL and blazing-fast full-text search.**
44

5-
Open Source, production ready Python FastAPI/Postgres app.
5+
---
66

7-
[GitHub](https://github.com/goldlabelapps/python) |
8-
[onr]Render](https://nx-ai.onrender.com) |
9-
[by Goldlabel](https://goldlabel.pro)
7+
### 🚀 Features
108

119
- **Python 3.11+**
12-
- **Postgres**
13-
- **tsvector** - Superfast full-text search (with GIN index)
10+
- **FastAPI** — Modern, high-performance REST API
11+
- **PostgreSQL** — Robust relational database
12+
- **tsvector + GIN** — Superfast full-text search
13+
- **Uvicorn** — Lightning-fast ASGI server
14+
- **Pytest** — Comprehensive testing
1415

15-
```sh
16-
uvicorn app.main:app --reload
17-
```
16+
---
17+
18+
## Project Overview
19+
20+
This project provides a scalable API backend using FastAPI and PostgreSQL, featuring:
1821

19-
#### Install
22+
- Automatic full-text search on all text fields (via tsvector)
23+
- Endpoints for health checks, product management, prompt handling, and prospect management
24+
- Efficient ingestion and processing of large CSV files
2025

21-
Create an environment file and add Postgres credentials etc
26+
---
2227

23-
`cp .env.sample .env`
28+
## Getting Started
29+
30+
### 1. Clone & Setup Environment
2431

2532
```bash
33+
git clone <repo-url>
34+
cd python
35+
cp .env.sample .env # Add your Postgres credentials and settings
2636
python -m venv venv
2737
source venv/bin/activate
2838
pip install -r requirements.txt
39+
```
40+
41+
### 2. Run the App
42+
43+
```bash
2944
uvicorn app.main:app --reload
3045
```
3146

32-
[localhost](http://localhost:8000) | [onrender](https://nx-ai.onrender.com)
47+
Visit [localhost:8000](http://localhost:8000) or [onrender](https://nx-ai.onrender.com)
3348

49+
---
3450

35-
### Full-Text Search (tsvector)
51+
## API Documentation
3652

37-
The prospects table includes a `search_vector` column (type: tsvector) that is automatically computed from all text fields on insert. A GIN index is created for this column, enabling fast and scalable full-text search queries.
53+
FastAPI auto-generates interactive docs:
3854

39-
**How it works:**
55+
- [Swagger UI](http://localhost:8000/docs)
56+
- [ReDoc](http://localhost:8000/redoc)
4057

41-
- On every insert or update, the `search_vector` is computed from all text columns using PostgreSQL's `to_tsvector('english', ...)`.
42-
- The GIN index (`idx_prospects_search_vector`) allows efficient search queries like:
58+
---
59+
60+
## Full-Text Search (tsvector)
61+
62+
The `prospects` table includes a `search_vector` column (type: tsvector) computed from all text fields on insert/update. A GIN index enables fast, scalable full-text search:
4363

4464
```sql
4565
SELECT * FROM prospects WHERE search_vector @@ plainto_tsquery('english', 'search terms');
4666
```
4767

48-
This makes searching across all text fields in the prospects table extremely fast, even for large datasets.
49-
- **FastAPI** — RESTful API framework
50-
- **Uvicorn** — ASGI server
51-
- **Pytest** — testing framework
52-
- **HTTPX / TestClient**
68+
**How it works:**
69+
- On every insert/update, `search_vector` is computed using PostgreSQL's `to_tsvector('english', ...)`.
70+
- The GIN index (`idx_prospects_search_vector`) enables efficient search across large datasets.
71+
72+
---
73+
74+
## Processing Large CSV Files
75+
76+
The `/prospects/process` endpoint supports robust ingestion of large CSVs (e.g., 1300+ rows, 300KB+), following the same normalization and insertion pattern as `/prospects/seed` but optimized for scale.
77+
78+
---
79+
80+
## Directory Structure
81+
82+
```
83+
app/
84+
main.py # FastAPI entrypoint
85+
api/ # API endpoints & schemas
86+
health.py
87+
root.py
88+
routes.py
89+
products/
90+
prompts/
91+
prospects/
92+
resend/
93+
utils/
94+
static/ # Static assets (e.g., repoicon.png)
95+
utils/ # Utility scripts
96+
tests/ # Pytest test suite
97+
requirements.txt # Python dependencies
98+
render.yaml # Deployment config (Render.com)
99+
```
100+
101+
---
102+
103+
## Contributing
104+
105+
Contributions are welcome! Please open issues or submit pull requests.
106+
107+
---
53108

54-
#### Docs
109+
## License
55110

56-
FastAPI automatically generates interactive documentation:
111+
This project is licensed under the MIT License. See [LICENSE](LICENSE) for details.
57112

58-
- Swagger UI: <http://localhost:8000/docs>
59-
- ReDoc: <http://localhost:8000/redoc>
113+
---
60114

61-
### Processing Large CSV Files
115+
## Contact
62116

63-
The `/prospects/process` endpoint is designed for robust, scalable ingestion of large CSV files (e.g., 1300+ rows, 300KB+). It follows the same normalization and insertion pattern as `/prospects/seed`, but is optimized for large files:
117+
For questions or support, open an issue or contact the maintainer.
64118

65119

app/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
"""Python - FastAPI, Postgres, tsvector"""
22

33
# Current Version
4-
__version__ = "2.0.8"
4+
__version__ = "2.1.1"
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Script to reset all 'flag' and 'hide' values to false in the prospects table
2+
from app.utils.db import get_db_connection
3+
4+
def reset_flag_and_hide():
5+
conn_gen = get_db_connection()
6+
conn = next(conn_gen)
7+
cur = conn.cursor()
8+
try:
9+
cur.execute("UPDATE prospects SET flag = FALSE, hide = FALSE;")
10+
conn.commit()
11+
print("All 'flag' and 'hide' values reset to FALSE.")
12+
except Exception as e:
13+
print(f"Error: {e}")
14+
conn.rollback()
15+
finally:
16+
cur.close()
17+
conn.close()
18+
19+
if __name__ == "__main__":
20+
reset_flag_and_hide()

app/utils/make_meta.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ def make_meta(severity: str, title: str) -> dict:
1010
"version": __version__,
1111
"time": epoch,
1212
"severity": severity,
13-
"message": title,
14-
"base_url": base_url,
13+
"title": title,
14+
"base": base_url,
1515
}

tests/prospects/test_prospects.py

Lines changed: 0 additions & 31 deletions
This file was deleted.

tests/test_prospects.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import pytest
2+
from fastapi.testclient import TestClient
3+
from app.main import app
4+
5+
client = TestClient(app)
6+
7+
def test_get_prospects_root():
8+
response = client.get("/prospects")
9+
assert response.status_code == 200
10+
data = response.json()
11+
assert "meta" in data
12+
assert "data" in data
13+
assert isinstance(data["data"], list)
14+
# Check that the expected keys are present in the data list
15+
assert any("init" in item for item in data["data"])
16+
assert any("search" in item for item in data["data"])
17+
# Meta checks
18+
meta = data["meta"]
19+
assert meta["severity"] == "success"
20+
assert meta["title"] == "Prospects endpoint"
21+
22+
def test_prospects_returns_list():
23+
response = client.get("/prospects")
24+
assert response.status_code == 200
25+
data = response.json()
26+
assert "meta" in data
27+
assert "data" in data
28+
assert isinstance(data["data"], list) or isinstance(data["data"], dict)

0 commit comments

Comments
 (0)