fraq 0.2.2__tar.gz → 0.2.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. {fraq-0.2.2 → fraq-0.2.3}/CHANGELOG.md +23 -0
  2. {fraq-0.2.2 → fraq-0.2.3}/PKG-INFO +1 -1
  3. fraq-0.2.3/examples/cli-docker/run.py +63 -0
  4. fraq-0.2.3/examples/fastapi-docker/main.py +86 -0
  5. fraq-0.2.3/examples/fastapi-docker/run.py +98 -0
  6. fraq-0.2.3/examples/fullstack-docker/api/main.py +38 -0
  7. fraq-0.2.3/examples/fullstack-docker/frontend/app.py +60 -0
  8. fraq-0.2.3/examples/fullstack-docker/websocket/main.py +52 -0
  9. fraq-0.2.3/examples/websocket-docker/main.py +104 -0
  10. {fraq-0.2.2 → fraq-0.2.3}/fraq/__init__.py +1 -1
  11. {fraq-0.2.2 → fraq-0.2.3}/fraq.egg-info/SOURCES.txt +7 -0
  12. {fraq-0.2.2 → fraq-0.2.3}/pyproject.toml +1 -1
  13. {fraq-0.2.2 → fraq-0.2.3}/LICENSE +0 -0
  14. {fraq-0.2.2 → fraq-0.2.3}/MANIFEST.in +0 -0
  15. {fraq-0.2.2 → fraq-0.2.3}/README.md +0 -0
  16. {fraq-0.2.2 → fraq-0.2.3}/examples/api_server.py +0 -0
  17. {fraq-0.2.2 → fraq-0.2.3}/examples/app_integrations.py +0 -0
  18. {fraq-0.2.2 → fraq-0.2.3}/examples/applications.py +0 -0
  19. {fraq-0.2.2 → fraq-0.2.3}/examples/async_streaming.py +0 -0
  20. {fraq-0.2.2 → fraq-0.2.3}/examples/nlp2cmd_integration.py +0 -0
  21. {fraq-0.2.2 → fraq-0.2.3}/examples/query_examples.py +0 -0
  22. {fraq-0.2.2 → fraq-0.2.3}/examples/text2fraq_examples.py +0 -0
  23. {fraq-0.2.2 → fraq-0.2.3}/examples/text2fraq_files.py +0 -0
  24. {fraq-0.2.2 → fraq-0.2.3}/fraq/adapters.py +0 -0
  25. {fraq-0.2.2 → fraq-0.2.3}/fraq/cli.py +0 -0
  26. {fraq-0.2.2 → fraq-0.2.3}/fraq/core.py +0 -0
  27. {fraq-0.2.2 → fraq-0.2.3}/fraq/formats.py +0 -0
  28. {fraq-0.2.2 → fraq-0.2.3}/fraq/generators.py +0 -0
  29. {fraq-0.2.2 → fraq-0.2.3}/fraq/py.typed +0 -0
  30. {fraq-0.2.2 → fraq-0.2.3}/fraq/query.py +0 -0
  31. {fraq-0.2.2 → fraq-0.2.3}/fraq/schema_export.py +0 -0
  32. {fraq-0.2.2 → fraq-0.2.3}/fraq/streaming.py +0 -0
  33. {fraq-0.2.2 → fraq-0.2.3}/fraq/text2fraq.py +0 -0
  34. {fraq-0.2.2 → fraq-0.2.3}/setup.cfg +0 -0
  35. {fraq-0.2.2 → fraq-0.2.3}/tests/__init__.py +0 -0
  36. {fraq-0.2.2 → fraq-0.2.3}/tests/test_adapters.py +0 -0
  37. {fraq-0.2.2 → fraq-0.2.3}/tests/test_cli.py +0 -0
  38. {fraq-0.2.2 → fraq-0.2.3}/tests/test_core.py +0 -0
  39. {fraq-0.2.2 → fraq-0.2.3}/tests/test_formats.py +0 -0
  40. {fraq-0.2.2 → fraq-0.2.3}/tests/test_generators.py +0 -0
  41. {fraq-0.2.2 → fraq-0.2.3}/tests/test_query.py +0 -0
  42. {fraq-0.2.2 → fraq-0.2.3}/tests/test_schema_export.py +0 -0
  43. {fraq-0.2.2 → fraq-0.2.3}/tests/test_streaming.py +0 -0
  44. {fraq-0.2.2 → fraq-0.2.3}/tests/test_text2fraq.py +0 -0
@@ -2,6 +2,29 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.2.3] - 2026-03-17
6
+
7
+ ### Docs
8
+ - Update docs/README.md
9
+ - Update examples/cli-docker/README.md
10
+ - Update examples/fastapi-docker/README.md
11
+ - Update examples/fullstack-docker/README.md
12
+ - Update examples/websocket-docker/README.md
13
+ - Update project/context.md
14
+
15
+ ### Other
16
+ - Update Dockerfile.cli
17
+ - Update Dockerfile.websocket
18
+ - Update examples/cli-docker/Dockerfile
19
+ - Update examples/cli-docker/docker-compose.yml
20
+ - Update examples/cli-docker/run.sh
21
+ - Update examples/fastapi-docker/Dockerfile
22
+ - Update examples/fastapi-docker/docker-compose.yml
23
+ - Update examples/fastapi-docker/main.py
24
+ - Update examples/fastapi-docker/run.py
25
+ - Update examples/fastapi-docker/run.sh
26
+ - ... and 21 more files
27
+
5
28
  ## [0.2.2] - 2026-03-17
6
29
 
7
30
  ### Docs
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fraq
3
- Version: 0.2.2
3
+ Version: 0.2.3
4
4
  Summary: Fractal Query Data Library — model data as infinite, self-similar fractal structures
5
5
  Author: Softreck / Prototypowanie.pl
6
6
  Author-email: Tom Sapletta <tom@sapletta.com>
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ CLI Docker — Wrapper do uruchamiania fraq CLI w Dockerze
4
+
5
+ Użycie:
6
+ python run.py files search --ext pdf --limit 10 /data
7
+ python run.py nl "pokaż 10 plików"
8
+ python run.py --local explore --depth 5 # lokalnie, bez Docker
9
+ """
10
+
11
+ import argparse
12
+ import subprocess
13
+ import sys
14
+ import os
15
+
16
+
17
+ def run_in_docker(args_list):
18
+ """Uruchom fraq CLI w Docker"""
19
+ cmd = ["docker-compose", "run", "--rm", "fraq-cli"] + args_list
20
+
21
+ print(f"🐳 Docker: {' '.join(cmd)}")
22
+ print("")
23
+
24
+ result = subprocess.run(cmd)
25
+ return result.returncode
26
+
27
+
28
+ def run_local(args_list):
29
+ """Uruchom fraq CLI lokalnie"""
30
+ cmd = ["fraq"] + args_list
31
+
32
+ print(f"🌀 Local: {' '.join(cmd)}")
33
+ print("")
34
+
35
+ result = subprocess.run(cmd)
36
+ return result.returncode
37
+
38
+
39
+ def main():
40
+ # Parsuj argumenty - przekaż wszystko do fraq
41
+ parser = argparse.ArgumentParser(
42
+ description="CLI Docker wrapper",
43
+ add_help=False
44
+ )
45
+ parser.add_argument("--local", action="store_true", help="Uruchom lokalnie (bez Docker)")
46
+ parser.add_argument("--docker", action="store_true", help="Wymuś Docker")
47
+
48
+ # Znajdź --local/--docker przed przekazaniem reszty
49
+ args, remaining = parser.parse_known_args()
50
+
51
+ # Jeśli nie ma argumentów, pokaż help
52
+ if not remaining:
53
+ remaining = ["--help"]
54
+
55
+ # Uruchom
56
+ if args.local:
57
+ return run_local(remaining)
58
+ else:
59
+ return run_in_docker(remaining)
60
+
61
+
62
+ if __name__ == "__main__":
63
+ sys.exit(main())
@@ -0,0 +1,86 @@
1
+ """
2
+ FastAPI + fraq Docker example
3
+ Minimal REST API for fractal queries and file search
4
+ """
5
+
6
+ from fastapi import FastAPI, Query
7
+ from fastapi.responses import JSONResponse
8
+ import os
9
+
10
+ from fraq import FileSearchAdapter, FraqNode, FraqExecutor, FraqQuery
11
+ from fraq.generators import HashGenerator
12
+ from fraq.formats import FormatRegistry
13
+
14
+ app = FastAPI(title="fraq Docker API", version="0.2.2")
15
+
16
+ # Config from env
17
+ FRAQ_DIMS = int(os.getenv("FRAQ_DIMS", "3"))
18
+ FRAQ_SEED = int(os.getenv("FRAQ_SEED", "0"))
19
+
20
+
21
+ @app.get("/")
22
+ def root():
23
+ return {"service": "fraq-docker", "version": "0.2.2", "dims": FRAQ_DIMS}
24
+
25
+
26
+ @app.get("/health")
27
+ def health():
28
+ return {"status": "ok"}
29
+
30
+
31
+ @app.get("/explore")
32
+ def explore(
33
+ depth: int = Query(3, ge=1, le=20),
34
+ dims: int = Query(FRAQ_DIMS, ge=1, le=10),
35
+ format: str = Query("json"),
36
+ ):
37
+ """Explore fractal structure"""
38
+ pos = tuple(0.0 for _ in range(dims))
39
+ root = FraqNode(position=pos, seed=FRAQ_SEED, generator=HashGenerator())
40
+ node = root.zoom(steps=depth)
41
+ data = node.to_dict(max_depth=1)
42
+ return JSONResponse(content=data)
43
+
44
+
45
+ @app.get("/files/search")
46
+ def files_search(
47
+ path: str = Query("/host/home", description="Directory to search"),
48
+ ext: str | None = Query(None, description="File extension"),
49
+ limit: int = Query(10, ge=1, le=1000),
50
+ sort: str = Query("mtime", regex="^(name|mtime|size)$"),
51
+ ):
52
+ """Search files with fractal metadata"""
53
+ try:
54
+ adapter = FileSearchAdapter(base_path=path, recursive=True)
55
+ results = adapter.search(extension=ext, limit=limit, sort_by=sort)
56
+ return {"path": path, "count": len(results), "files": results}
57
+ except Exception as e:
58
+ return {"error": str(e)}
59
+
60
+
61
+ @app.get("/files/stat/{file_path:path}")
62
+ def files_stat(file_path: str):
63
+ """Get file statistics with fractal coordinates"""
64
+ from pathlib import Path
65
+ from datetime import datetime
66
+
67
+ path = Path(file_path)
68
+ if not path.exists():
69
+ return {"error": "File not found"}
70
+
71
+ stat = path.stat()
72
+ return {
73
+ "filename": path.name,
74
+ "path": str(path.absolute()),
75
+ "size": stat.st_size,
76
+ "mtime": datetime.fromtimestamp(stat.st_mtime).isoformat(),
77
+ "fraq": {
78
+ "seed": hash(str(path)) % (2**32),
79
+ "value": hash(str(path)) / (2**32),
80
+ }
81
+ }
82
+
83
+
84
+ if __name__ == "__main__":
85
+ import uvicorn
86
+ uvicorn.run(app, host="0.0.0.0", port=8000)
@@ -0,0 +1,98 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ FastAPI Docker — Uruchomienie bez Docker (opcjonalnie)
4
+
5
+ Użycie:
6
+ python run.py # Uruchom serwer lokalnie (bez Docker)
7
+ python run.py --docker # Uruchom przez Docker
8
+ """
9
+
10
+ import argparse
11
+ import subprocess
12
+ import sys
13
+ import os
14
+
15
+
16
+ def run_local():
17
+ """Uruchom serwer lokalnie (bez Docker)"""
18
+ print("🌀 Uruchamianie FastAPI lokalnie...")
19
+ try:
20
+ import uvicorn
21
+ from main import app
22
+ uvicorn.run(app, host="0.0.0.0", port=8000)
23
+ except ImportError:
24
+ print("❌ Brakujące zależności. Zainstaluj:")
25
+ print(" pip install fraq fastapi uvicorn")
26
+ sys.exit(1)
27
+
28
+
29
+ def run_docker():
30
+ """Uruchom przez Docker"""
31
+ print("🐳 Uruchamianie przez Docker...")
32
+ subprocess.run(["docker-compose", "up", "--build", "-d"], check=True)
33
+ print("\n✅ Serwer działa na http://localhost:8000")
34
+ print("\nTestuj:")
35
+ print(" curl http://localhost:8000/health")
36
+
37
+
38
+ def stop_docker():
39
+ """Zatrzymaj Docker"""
40
+ print("🛑 Zatrzymywanie Dockera...")
41
+ subprocess.run(["docker-compose", "down"], check=True)
42
+ print("✅ Zatrzymano")
43
+
44
+
45
+ def test_api():
46
+ """Przetestuj API"""
47
+ import requests
48
+ import json
49
+
50
+ base = "http://localhost:8000"
51
+
52
+ print("🧪 Testowanie API...")
53
+
54
+ # Health
55
+ try:
56
+ r = requests.get(f"{base}/health", timeout=5)
57
+ print(f"✅ Health: {r.json()}")
58
+ except Exception as e:
59
+ print(f"❌ Health failed: {e}")
60
+ return
61
+
62
+ # Files search
63
+ try:
64
+ r = requests.get(f"{base}/files/search?ext=py&limit=3", timeout=10)
65
+ data = r.json()
66
+ print(f"✅ Files search: {data.get('count', 0)} files found")
67
+ except Exception as e:
68
+ print(f"❌ Files search failed: {e}")
69
+
70
+ # Explore
71
+ try:
72
+ r = requests.get(f"{base}/explore?depth=2", timeout=10)
73
+ data = r.json()
74
+ print(f"✅ Explore: fractal depth={data.get('depth', 'N/A')}")
75
+ except Exception as e:
76
+ print(f"❌ Explore failed: {e}")
77
+
78
+
79
+ def main():
80
+ parser = argparse.ArgumentParser(description="FastAPI + fraq runner")
81
+ parser.add_argument("--docker", action="store_true", help="Użyj Docker")
82
+ parser.add_argument("--stop", action="store_true", help="Zatrzymaj Docker")
83
+ parser.add_argument("--test", action="store_true", help="Przetestuj API")
84
+
85
+ args = parser.parse_args()
86
+
87
+ if args.stop:
88
+ stop_docker()
89
+ elif args.test:
90
+ test_api()
91
+ elif args.docker:
92
+ run_docker()
93
+ else:
94
+ run_local()
95
+
96
+
97
+ if __name__ == "__main__":
98
+ main()
@@ -0,0 +1,38 @@
1
+ """
2
+ Fullstack - API service
3
+ """
4
+ from fastapi import FastAPI, Query
5
+ from fastapi.responses import JSONResponse
6
+
7
+ from fraq import FileSearchAdapter, FraqNode
8
+ from fraq.generators import HashGenerator
9
+
10
+ app = FastAPI(title="fraq Fullstack API")
11
+
12
+
13
+ @app.get("/")
14
+ def root():
15
+ return {"service": "api", "version": "0.2.2"}
16
+
17
+
18
+ @app.get("/health")
19
+ def health():
20
+ return {"status": "ok"}
21
+
22
+
23
+ @app.get("/explore")
24
+ def explore(depth: int = Query(3)):
25
+ root = FraqNode(position=(0.0, 0.0, 0.0), generator=HashGenerator())
26
+ node = root.zoom(steps=depth)
27
+ return JSONResponse(content=node.to_dict(max_depth=1))
28
+
29
+
30
+ @app.get("/files/search")
31
+ def files_search(
32
+ path: str = Query("/data"),
33
+ ext: str | None = Query(None),
34
+ limit: int = Query(10),
35
+ ):
36
+ adapter = FileSearchAdapter(base_path=path, recursive=True)
37
+ results = adapter.search(extension=ext, limit=limit, sort_by="mtime")
38
+ return {"count": len(results), "files": results}
@@ -0,0 +1,60 @@
1
+ """
2
+ Fullstack - Streamlit Frontend
3
+ """
4
+ import streamlit as st
5
+ import requests
6
+ import json
7
+ import os
8
+
9
+ API_URL = os.getenv("API_URL", "http://localhost:8000")
10
+ WS_URL = os.getenv("WS_URL", "ws://localhost:8001")
11
+
12
+ st.set_page_config(page_title="fraq UI", layout="wide")
13
+
14
+ st.title("🌀 fraq — Fractal Query Data Library")
15
+
16
+ # Sidebar
17
+ st.sidebar.header("Konfiguracja")
18
+ path = st.sidebar.text_input("Ścieżka", "/data")
19
+ ext_filter = st.sidebar.text_input("Rozszerzenie", "py")
20
+ limit = st.sidebar.slider("Limit", 1, 100, 10)
21
+
22
+ # Tabs
23
+ tab1, tab2, tab3 = st.tabs(["🔍 Wyszukiwanie plików", "🌐 API REST", "ℹ️ Info"])
24
+
25
+ with tab1:
26
+ st.subheader("Wyszukiwanie plików")
27
+ if st.button("Szukaj"):
28
+ try:
29
+ resp = requests.get(f"{API_URL}/files/search", params={
30
+ "path": path, "ext": ext_filter or None, "limit": limit
31
+ })
32
+ data = resp.json()
33
+ if data.get("files"):
34
+ st.write(f"Znaleziono {data['count']} plików:")
35
+ for f in data["files"]:
36
+ st.code(f"{f['filename']} ({f['size']} bytes)")
37
+ else:
38
+ st.warning("Brak wyników")
39
+ except Exception as e:
40
+ st.error(f"Błąd: {e}")
41
+
42
+ with tab2:
43
+ st.subheader("Test API")
44
+ st.code(f"GET {API_URL}/health", language="bash")
45
+ try:
46
+ health = requests.get(f"{API_URL}/health").json()
47
+ st.json(health)
48
+ except Exception as e:
49
+ st.error(f"API niedostępne: {e}")
50
+
51
+ with tab3:
52
+ st.subheader("API Endpoints")
53
+ st.markdown("""
54
+ - `GET /health` — Health check
55
+ - `GET /explore?depth=3` — Eksploracja fraktala
56
+ - `GET /files/search?ext=pdf&limit=10` — Wyszukiwanie plików
57
+ - `WS /ws/stream` — WebSocket streaming
58
+ """)
59
+ st.info(f"API URL: {API_URL}")
60
+ st.info(f"WebSocket URL: {WS_URL}")
@@ -0,0 +1,52 @@
1
+ """
2
+ Fullstack - WebSocket service
3
+ """
4
+ import asyncio
5
+ from fastapi import FastAPI, WebSocket, WebSocketDisconnect
6
+
7
+ from fraq import FileSearchAdapter, FraqNode
8
+ from fraq.generators import HashGenerator
9
+
10
+ app = FastAPI(title="fraq Fullstack WebSocket")
11
+
12
+
13
+ @app.websocket("/ws/stream")
14
+ async def ws_stream(websocket: WebSocket):
15
+ await websocket.accept()
16
+ try:
17
+ while True:
18
+ msg = await websocket.receive_json()
19
+ if msg.get("action") == "stream":
20
+ count = msg.get("count", 10)
21
+ root = FraqNode(position=(0.0, 0.0, 0.0), generator=HashGenerator())
22
+ cursor = root.cursor()
23
+ for i in range(count):
24
+ cursor.advance()
25
+ await websocket.send_json({"index": i, "value": cursor.current.value})
26
+ await asyncio.sleep(0.1)
27
+ except WebSocketDisconnect:
28
+ pass
29
+
30
+
31
+ @app.websocket("/ws/files")
32
+ async def ws_files(websocket: WebSocket):
33
+ await websocket.accept()
34
+ try:
35
+ while True:
36
+ msg = await websocket.receive_json()
37
+ if msg.get("action") == "search":
38
+ path = msg.get("path", "/data")
39
+ ext = msg.get("ext")
40
+ limit = msg.get("limit", 10)
41
+ adapter = FileSearchAdapter(base_path=path, recursive=True)
42
+ for record in adapter.stream(extension=ext, count=limit):
43
+ await websocket.send_json(record)
44
+ await asyncio.sleep(0.01)
45
+ await websocket.send_json({"done": True})
46
+ except WebSocketDisconnect:
47
+ pass
48
+
49
+
50
+ @app.get("/health")
51
+ def health():
52
+ return {"status": "ok"}
@@ -0,0 +1,104 @@
1
+ """
2
+ WebSocket + fraq Docker example
3
+ Real-time streaming of fractal data and file search
4
+ """
5
+
6
+ import asyncio
7
+ import json
8
+ from fastapi import FastAPI, WebSocket, WebSocketDisconnect
9
+
10
+ from fraq import FileSearchAdapter, FraqNode
11
+ from fraq.generators import HashGenerator
12
+
13
+ app = FastAPI(title="fraq WebSocket Docker", version="0.2.2")
14
+
15
+
16
+ @app.websocket("/ws/stream")
17
+ async def ws_stream(websocket: WebSocket):
18
+ """Stream fractal data"""
19
+ await websocket.accept()
20
+ try:
21
+ while True:
22
+ msg = await websocket.receive_json()
23
+ action = msg.get("action")
24
+
25
+ if action == "stream":
26
+ count = msg.get("count", 10)
27
+ interval = msg.get("interval", 0.1)
28
+
29
+ # Generate fractal stream
30
+ root = FraqNode(position=(0.0, 0.0, 0.0), generator=HashGenerator())
31
+ cursor = root.cursor()
32
+
33
+ for i in range(count):
34
+ cursor.advance()
35
+ await websocket.send_json({
36
+ "index": i,
37
+ "value": cursor.current.value,
38
+ "position": cursor.current.position,
39
+ })
40
+ await asyncio.sleep(interval)
41
+
42
+ elif action == "ping":
43
+ await websocket.send_json({"pong": True, "timestamp": asyncio.get_event_loop().time()})
44
+
45
+ except WebSocketDisconnect:
46
+ print("Client disconnected from /ws/stream")
47
+
48
+
49
+ @app.websocket("/ws/files")
50
+ async def ws_files(websocket: WebSocket):
51
+ """Stream file search results"""
52
+ await websocket.accept()
53
+ try:
54
+ while True:
55
+ msg = await websocket.receive_json()
56
+ action = msg.get("action")
57
+
58
+ if action == "search":
59
+ path = msg.get("path", "/data")
60
+ ext = msg.get("ext")
61
+ pattern = msg.get("pattern")
62
+ limit = msg.get("limit", 10)
63
+
64
+ adapter = FileSearchAdapter(base_path=path, recursive=True)
65
+
66
+ # Stream results one by one
67
+ count = 0
68
+ for record in adapter.stream(extension=ext, pattern=pattern, count=limit):
69
+ await websocket.send_json(record)
70
+ count += 1
71
+ await asyncio.sleep(0.01)
72
+
73
+ await websocket.send_json({"done": True, "count": count})
74
+
75
+ elif action == "stat":
76
+ from pathlib import Path
77
+ from datetime import datetime
78
+
79
+ file_path = msg.get("file")
80
+ path = Path(file_path)
81
+
82
+ if path.exists():
83
+ stat = path.stat()
84
+ await websocket.send_json({
85
+ "file": str(path),
86
+ "size": stat.st_size,
87
+ "mtime": datetime.fromtimestamp(stat.st_mtime).isoformat(),
88
+ "fraq_seed": hash(str(path)) % (2**32),
89
+ })
90
+ else:
91
+ await websocket.send_json({"error": "File not found"})
92
+
93
+ except WebSocketDisconnect:
94
+ print("Client disconnected from /ws/files")
95
+
96
+
97
+ @app.get("/health")
98
+ def health():
99
+ return {"status": "ok", "websocket": True}
100
+
101
+
102
+ if __name__ == "__main__":
103
+ import uvicorn
104
+ uvicorn.run(app, host="0.0.0.0", port=8001)
@@ -44,7 +44,7 @@ from fraq.text2fraq import (
44
44
  text2filesearch,
45
45
  )
46
46
 
47
- __version__ = "0.2.2"
47
+ __version__ = "0.2.3"
48
48
  __all__ = [
49
49
  "FraqNode", "FraqSchema", "FraqCursor",
50
50
  "FormatRegistry",
@@ -12,6 +12,13 @@ examples/nlp2cmd_integration.py
12
12
  examples/query_examples.py
13
13
  examples/text2fraq_examples.py
14
14
  examples/text2fraq_files.py
15
+ examples/cli-docker/run.py
16
+ examples/fastapi-docker/main.py
17
+ examples/fastapi-docker/run.py
18
+ examples/fullstack-docker/api/main.py
19
+ examples/fullstack-docker/frontend/app.py
20
+ examples/fullstack-docker/websocket/main.py
21
+ examples/websocket-docker/main.py
15
22
  fraq/__init__.py
16
23
  fraq/adapters.py
17
24
  fraq/cli.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "fraq"
7
- version = "0.2.2"
7
+ version = "0.2.3"
8
8
  description = "Fractal Query Data Library — model data as infinite, self-similar fractal structures"
9
9
  readme = "README.md"
10
10
  license = "Apache-2.0"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes