sf
This commit is contained in:
parent
655e59c433
commit
fef9abdd4f
@ -10,4 +10,5 @@ urlpatterns = [
|
|||||||
path('', config_views.config_dashboard, name='dashboard'),
|
path('', config_views.config_dashboard, name='dashboard'),
|
||||||
path('sla/', config_views.sla_config_list, name='sla_config_list'),
|
path('sla/', config_views.sla_config_list, name='sla_config_list'),
|
||||||
path('routing/', config_views.routing_rules_list, name='routing_rules_list'),
|
path('routing/', config_views.routing_rules_list, name='routing_rules_list'),
|
||||||
|
path('test/',config_views.test, name='test'),
|
||||||
]
|
]
|
||||||
|
|||||||
@ -18,18 +18,18 @@ def config_dashboard(request):
|
|||||||
from django.shortcuts import redirect
|
from django.shortcuts import redirect
|
||||||
messages.error(request, "Only PX Admins can access configuration.")
|
messages.error(request, "Only PX Admins can access configuration.")
|
||||||
return redirect('dashboard:command-center')
|
return redirect('dashboard:command-center')
|
||||||
|
|
||||||
# Get counts
|
# Get counts
|
||||||
sla_configs_count = PXActionSLAConfig.objects.filter(is_active=True).count()
|
sla_configs_count = PXActionSLAConfig.objects.filter(is_active=True).count()
|
||||||
routing_rules_count = RoutingRule.objects.filter(is_active=True).count()
|
routing_rules_count = RoutingRule.objects.filter(is_active=True).count()
|
||||||
hospitals_count = Hospital.objects.filter(status='active').count()
|
hospitals_count = Hospital.objects.filter(status='active').count()
|
||||||
|
|
||||||
context = {
|
context = {
|
||||||
'sla_configs_count': sla_configs_count,
|
'sla_configs_count': sla_configs_count,
|
||||||
'routing_rules_count': routing_rules_count,
|
'routing_rules_count': routing_rules_count,
|
||||||
'hospitals_count': hospitals_count,
|
'hospitals_count': hospitals_count,
|
||||||
}
|
}
|
||||||
|
|
||||||
return render(request, 'config/dashboard.html', context)
|
return render(request, 'config/dashboard.html', context)
|
||||||
|
|
||||||
|
|
||||||
@ -42,39 +42,39 @@ def sla_config_list(request):
|
|||||||
from django.shortcuts import redirect
|
from django.shortcuts import redirect
|
||||||
messages.error(request, "Only PX Admins can access configuration.")
|
messages.error(request, "Only PX Admins can access configuration.")
|
||||||
return redirect('dashboard:command-center')
|
return redirect('dashboard:command-center')
|
||||||
|
|
||||||
queryset = PXActionSLAConfig.objects.select_related('hospital', 'department')
|
queryset = PXActionSLAConfig.objects.select_related('hospital', 'department')
|
||||||
|
|
||||||
# Apply filters
|
# Apply filters
|
||||||
hospital_filter = request.GET.get('hospital')
|
hospital_filter = request.GET.get('hospital')
|
||||||
if hospital_filter:
|
if hospital_filter:
|
||||||
queryset = queryset.filter(hospital_id=hospital_filter)
|
queryset = queryset.filter(hospital_id=hospital_filter)
|
||||||
|
|
||||||
is_active = request.GET.get('is_active')
|
is_active = request.GET.get('is_active')
|
||||||
if is_active == 'true':
|
if is_active == 'true':
|
||||||
queryset = queryset.filter(is_active=True)
|
queryset = queryset.filter(is_active=True)
|
||||||
elif is_active == 'false':
|
elif is_active == 'false':
|
||||||
queryset = queryset.filter(is_active=False)
|
queryset = queryset.filter(is_active=False)
|
||||||
|
|
||||||
# Ordering
|
# Ordering
|
||||||
queryset = queryset.order_by('hospital', 'name')
|
queryset = queryset.order_by('hospital', 'name')
|
||||||
|
|
||||||
# Pagination
|
# Pagination
|
||||||
page_size = int(request.GET.get('page_size', 25))
|
page_size = int(request.GET.get('page_size', 25))
|
||||||
paginator = Paginator(queryset, page_size)
|
paginator = Paginator(queryset, page_size)
|
||||||
page_number = request.GET.get('page', 1)
|
page_number = request.GET.get('page', 1)
|
||||||
page_obj = paginator.get_page(page_number)
|
page_obj = paginator.get_page(page_number)
|
||||||
|
|
||||||
# Get hospitals for filter
|
# Get hospitals for filter
|
||||||
hospitals = Hospital.objects.filter(status='active')
|
hospitals = Hospital.objects.filter(status='active')
|
||||||
|
|
||||||
context = {
|
context = {
|
||||||
'page_obj': page_obj,
|
'page_obj': page_obj,
|
||||||
'sla_configs': page_obj.object_list,
|
'sla_configs': page_obj.object_list,
|
||||||
'hospitals': hospitals,
|
'hospitals': hospitals,
|
||||||
'filters': request.GET,
|
'filters': request.GET,
|
||||||
}
|
}
|
||||||
|
|
||||||
return render(request, 'config/sla_config.html', context)
|
return render(request, 'config/sla_config.html', context)
|
||||||
|
|
||||||
|
|
||||||
@ -87,39 +87,50 @@ def routing_rules_list(request):
|
|||||||
from django.shortcuts import redirect
|
from django.shortcuts import redirect
|
||||||
messages.error(request, "Only PX Admins can access configuration.")
|
messages.error(request, "Only PX Admins can access configuration.")
|
||||||
return redirect('dashboard:command-center')
|
return redirect('dashboard:command-center')
|
||||||
|
|
||||||
queryset = RoutingRule.objects.select_related(
|
queryset = RoutingRule.objects.select_related(
|
||||||
'hospital', 'department', 'assign_to_user', 'assign_to_department'
|
'hospital', 'department', 'assign_to_user', 'assign_to_department'
|
||||||
)
|
)
|
||||||
|
|
||||||
# Apply filters
|
# Apply filters
|
||||||
hospital_filter = request.GET.get('hospital')
|
hospital_filter = request.GET.get('hospital')
|
||||||
if hospital_filter:
|
if hospital_filter:
|
||||||
queryset = queryset.filter(hospital_id=hospital_filter)
|
queryset = queryset.filter(hospital_id=hospital_filter)
|
||||||
|
|
||||||
is_active = request.GET.get('is_active')
|
is_active = request.GET.get('is_active')
|
||||||
if is_active == 'true':
|
if is_active == 'true':
|
||||||
queryset = queryset.filter(is_active=True)
|
queryset = queryset.filter(is_active=True)
|
||||||
elif is_active == 'false':
|
elif is_active == 'false':
|
||||||
queryset = queryset.filter(is_active=False)
|
queryset = queryset.filter(is_active=False)
|
||||||
|
|
||||||
# Ordering
|
# Ordering
|
||||||
queryset = queryset.order_by('-priority', 'name')
|
queryset = queryset.order_by('-priority', 'name')
|
||||||
|
|
||||||
# Pagination
|
# Pagination
|
||||||
page_size = int(request.GET.get('page_size', 25))
|
page_size = int(request.GET.get('page_size', 25))
|
||||||
paginator = Paginator(queryset, page_size)
|
paginator = Paginator(queryset, page_size)
|
||||||
page_number = request.GET.get('page', 1)
|
page_number = request.GET.get('page', 1)
|
||||||
page_obj = paginator.get_page(page_number)
|
page_obj = paginator.get_page(page_number)
|
||||||
|
|
||||||
# Get hospitals for filter
|
# Get hospitals for filter
|
||||||
hospitals = Hospital.objects.filter(status='active')
|
hospitals = Hospital.objects.filter(status='active')
|
||||||
|
|
||||||
context = {
|
context = {
|
||||||
'page_obj': page_obj,
|
'page_obj': page_obj,
|
||||||
'routing_rules': page_obj.object_list,
|
'routing_rules': page_obj.object_list,
|
||||||
'hospitals': hospitals,
|
'hospitals': hospitals,
|
||||||
'filters': request.GET,
|
'filters': request.GET,
|
||||||
}
|
}
|
||||||
|
|
||||||
return render(request, 'config/routing_rules.html', context)
|
return render(request, 'config/routing_rules.html', context)
|
||||||
|
|
||||||
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
|
from rich import print
|
||||||
|
@csrf_exempt
|
||||||
|
def test(request):
|
||||||
|
import json
|
||||||
|
from django.http import JsonResponse
|
||||||
|
|
||||||
|
print(json.loads(request.body))
|
||||||
|
|
||||||
|
return JsonResponse({'status': 'ok'})
|
||||||
@ -18,7 +18,7 @@ def health_check(request):
|
|||||||
'status': 'ok',
|
'status': 'ok',
|
||||||
'services': {}
|
'services': {}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check database connection
|
# Check database connection
|
||||||
try:
|
try:
|
||||||
with connection.cursor() as cursor:
|
with connection.cursor() as cursor:
|
||||||
@ -27,7 +27,7 @@ def health_check(request):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
health_status['status'] = 'error'
|
health_status['status'] = 'error'
|
||||||
health_status['services']['database'] = f'error: {str(e)}'
|
health_status['services']['database'] = f'error: {str(e)}'
|
||||||
|
|
||||||
# Check Redis/Celery (optional - don't fail if not available)
|
# Check Redis/Celery (optional - don't fail if not available)
|
||||||
try:
|
try:
|
||||||
from django_celery_beat.models import PeriodicTask
|
from django_celery_beat.models import PeriodicTask
|
||||||
@ -35,8 +35,9 @@ def health_check(request):
|
|||||||
health_status['services']['celery_beat'] = 'ok'
|
health_status['services']['celery_beat'] = 'ok'
|
||||||
except Exception:
|
except Exception:
|
||||||
health_status['services']['celery_beat'] = 'not_configured'
|
health_status['services']['celery_beat'] = 'not_configured'
|
||||||
|
|
||||||
# Return appropriate status code
|
# Return appropriate status code
|
||||||
status_code = 200 if health_status['status'] == 'ok' else 503
|
status_code = 200 if health_status['status'] == 'ok' else 503
|
||||||
|
|
||||||
return JsonResponse(health_status, status=status_code)
|
return JsonResponse(health_status, status=status_code)
|
||||||
|
|
||||||
|
|||||||
@ -9,13 +9,19 @@ ALLOWED_HOSTS = ['localhost', '127.0.0.1', '0.0.0.0']
|
|||||||
|
|
||||||
# Database - Use PostgreSQL even in dev for consistency
|
# Database - Use PostgreSQL even in dev for consistency
|
||||||
# Override with SQLite if needed for quick local testing
|
# Override with SQLite if needed for quick local testing
|
||||||
DATABASES = {
|
# DATABASES = {
|
||||||
'default': env.db(
|
# 'default': env.db(
|
||||||
'DATABASE_URL',
|
# 'DATABASE_URL',
|
||||||
default='postgresql://px360:px360@localhost:5432/px360'
|
# default='postgresql://px360:px360@localhost:5432/px360'
|
||||||
)
|
# )
|
||||||
}
|
# }
|
||||||
|
|
||||||
|
DATABASES = {
|
||||||
|
'default': {
|
||||||
|
'ENGINE': 'django.db.backends.sqlite3',
|
||||||
|
'NAME': BASE_DIR / 'db.sqlite3',
|
||||||
|
}
|
||||||
|
}
|
||||||
# Email backend for development
|
# Email backend for development
|
||||||
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
|
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
|
||||||
|
|
||||||
@ -29,7 +35,7 @@ CORS_ALLOW_ALL_ORIGINS = True
|
|||||||
# Django Debug Toolbar (optional)
|
# Django Debug Toolbar (optional)
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
INSTALLED_APPS += ['django_extensions'] # noqa
|
INSTALLED_APPS += ['django_extensions'] # noqa
|
||||||
|
|
||||||
# Logging - More verbose in development
|
# Logging - More verbose in development
|
||||||
LOGGING['loggers']['django']['level'] = 'DEBUG' # noqa
|
LOGGING['loggers']['django']['level'] = 'DEBUG' # noqa
|
||||||
LOGGING['loggers']['apps']['level'] = 'DEBUG' # noqa
|
LOGGING['loggers']['apps']['level'] = 'DEBUG' # noqa
|
||||||
|
|||||||
@ -23,6 +23,7 @@ dependencies = [
|
|||||||
"whitenoise>=6.6.0",
|
"whitenoise>=6.6.0",
|
||||||
"django-extensions>=4.1",
|
"django-extensions>=4.1",
|
||||||
"djangorestframework-stubs>=3.16.6",
|
"djangorestframework-stubs>=3.16.6",
|
||||||
|
"rich>=14.2.0",
|
||||||
"reportlab>=4.4.7",
|
"reportlab>=4.4.7",
|
||||||
"openpyxl>=3.1.5",
|
"openpyxl>=3.1.5",
|
||||||
]
|
]
|
||||||
|
|||||||
117
run.py
Normal file
117
run.py
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
import json
|
||||||
|
import time
|
||||||
|
import random
|
||||||
|
import uuid
|
||||||
|
import requests
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
|
# Configuration
|
||||||
|
API_ENDPOINT = "http://localhost:8000/config/test/" # Update with your actual endpoint
|
||||||
|
SIMULATION_SPEED_FACTOR = 1 # 1 is real-time, higher is faster
|
||||||
|
BATCH_SIZE = 1 # Number of events to send at once
|
||||||
|
|
||||||
|
# Mock Data Constants
|
||||||
|
DEPARTMENTS = ["Emergency", "Cardiology", "Pediatrics", "Radiology", "General Medicine"]
|
||||||
|
VISIT_TYPES = ["Inpatient", "Outpatient", "Emergency"]
|
||||||
|
STAGES = ["Triage", "Consultation", "Diagnostic Testing", "Observation", "Discharge"]
|
||||||
|
ROLES = ["Doctor", "Nurse", "Technician", "Admin"]
|
||||||
|
|
||||||
|
# Staff Directory Simulation
|
||||||
|
STAFF_LIST = [
|
||||||
|
{
|
||||||
|
"staff_id": f"STF-{1000 + i}",
|
||||||
|
"first_name": f"StaffFirst_{i}",
|
||||||
|
"last_name": f"StaffLast_{i}",
|
||||||
|
"role": random.choice(ROLES),
|
||||||
|
"department": random.choice(DEPARTMENTS)
|
||||||
|
} for i in range(20)
|
||||||
|
]
|
||||||
|
|
||||||
|
def generate_patient_journey():
|
||||||
|
"""Generates a realistic patient journey payload with National ID and MRN."""
|
||||||
|
p_id = f"PAT-{random.randint(10000, 99999)}"
|
||||||
|
mrn = f"MRN-{random.randint(100000, 999999)}"
|
||||||
|
national_id = f"{random.randint(100, 999)}-{random.randint(10, 99)}-{random.randint(1000, 9999)}"
|
||||||
|
e_id = f"ENC-{uuid.uuid4().hex[:8].upper()}"
|
||||||
|
|
||||||
|
# Times
|
||||||
|
checkin = datetime.now() - timedelta(minutes=random.randint(30, 240))
|
||||||
|
|
||||||
|
payload = {
|
||||||
|
"patient_info": {
|
||||||
|
"patient_id": p_id,
|
||||||
|
"mrn": mrn,
|
||||||
|
"national_id": national_id,
|
||||||
|
"first_name": f"Patient_{p_id[-3:]}",
|
||||||
|
"last_name": "Doe",
|
||||||
|
"phone": f"+1-555-{random.randint(100, 999)}-{random.randint(1000, 9999)}"
|
||||||
|
},
|
||||||
|
"visit_info": {
|
||||||
|
"encounter_id": e_id,
|
||||||
|
"patient_id": p_id,
|
||||||
|
"visit_type": random.choice(VISIT_TYPES),
|
||||||
|
"department": random.choice(DEPARTMENTS),
|
||||||
|
"checkin_time": checkin.isoformat(),
|
||||||
|
"discharge_time": datetime.now().isoformat()
|
||||||
|
},
|
||||||
|
"journey_steps": []
|
||||||
|
}
|
||||||
|
|
||||||
|
# Generate 1 to 4 journey steps
|
||||||
|
num_steps = random.randint(1, 4)
|
||||||
|
step_time = checkin
|
||||||
|
|
||||||
|
for i in range(num_steps):
|
||||||
|
staff = random.choice(STAFF_LIST)
|
||||||
|
step_time += timedelta(minutes=random.randint(10, 45))
|
||||||
|
|
||||||
|
step = {
|
||||||
|
"encounter_id": e_id,
|
||||||
|
"patient_id": p_id,
|
||||||
|
"stage": STAGES[min(i, len(STAGES)-1)],
|
||||||
|
"timestamp": step_time.isoformat(),
|
||||||
|
"staff_id": staff["staff_id"],
|
||||||
|
"wait_minutes": random.randint(0, 30)
|
||||||
|
}
|
||||||
|
payload["journey_steps"].append(step)
|
||||||
|
|
||||||
|
return payload
|
||||||
|
|
||||||
|
def send_data(payload):
|
||||||
|
"""Sends the JSON payload to the configured endpoint."""
|
||||||
|
print(f"[{datetime.now().strftime('%H:%M:%S')}] Sending journey data for Patient MRN: {payload['patient_info']['mrn']}...")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Note: In a real scenario, you'd add headers={'Authorization': 'Bearer YOUR_TOKEN'}
|
||||||
|
response = requests.post(API_ENDPOINT, json=payload, timeout=10)
|
||||||
|
response.raise_for_status()
|
||||||
|
|
||||||
|
# Simulated success for demonstration
|
||||||
|
print(f"Successfully sent {len(payload['journey_steps'])} journey steps to {API_ENDPOINT}")
|
||||||
|
# print(json.dumps(payload, indent=2)) # Uncomment to see full payload
|
||||||
|
|
||||||
|
except requests.exceptions.RequestException as e:
|
||||||
|
print(f"Error sending data: {e}")
|
||||||
|
|
||||||
|
def run_simulation():
|
||||||
|
"""Main loop for the simulation."""
|
||||||
|
print("Starting PX360 Integration Simulation...")
|
||||||
|
print(f"Target Endpoint: {API_ENDPOINT}")
|
||||||
|
print("-" * 50)
|
||||||
|
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
# Generate and send data
|
||||||
|
data = generate_patient_journey()
|
||||||
|
send_data(data)
|
||||||
|
|
||||||
|
# Wait for a random interval between 2 and 10 seconds (scaled)
|
||||||
|
wait_time = random.uniform(2, 10) / SIMULATION_SPEED_FACTOR
|
||||||
|
print(f"Next event in {wait_time:.2f} seconds...\n")
|
||||||
|
time.sleep(wait_time)
|
||||||
|
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print("\nSimulation stopped by user.")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
run_simulation()
|
||||||
38
uv.lock
generated
38
uv.lock
generated
@ -1,5 +1,5 @@
|
|||||||
version = 1
|
version = 1
|
||||||
revision = 2
|
revision = 3
|
||||||
requires-python = ">=3.12"
|
requires-python = ">=3.12"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -609,6 +609,18 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/14/d6/943cf84117cd9ddecf6e1707a3f712a49fc64abdb8ac31b19132871af1dd/kombu-5.6.1-py3-none-any.whl", hash = "sha256:b69e3f5527ec32fc5196028a36376501682973e9620d6175d1c3d4eaf7e95409", size = 214141, upload-time = "2025-11-25T11:07:31.54Z" },
|
{ url = "https://files.pythonhosted.org/packages/14/d6/943cf84117cd9ddecf6e1707a3f712a49fc64abdb8ac31b19132871af1dd/kombu-5.6.1-py3-none-any.whl", hash = "sha256:b69e3f5527ec32fc5196028a36376501682973e9620d6175d1c3d4eaf7e95409", size = 214141, upload-time = "2025-11-25T11:07:31.54Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "markdown-it-py"
|
||||||
|
version = "4.0.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "mdurl" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/5b/f5/4ec618ed16cc4f8fb3b701563655a69816155e79e24a17b651541804721d/markdown_it_py-4.0.0.tar.gz", hash = "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3", size = 73070, upload-time = "2025-08-11T12:57:52.854Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl", hash = "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147", size = 87321, upload-time = "2025-08-11T12:57:51.923Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "matplotlib-inline"
|
name = "matplotlib-inline"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
@ -621,6 +633,15 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/af/33/ee4519fa02ed11a94aef9559552f3b17bb863f2ecfe1a35dc7f548cde231/matplotlib_inline-0.2.1-py3-none-any.whl", hash = "sha256:d56ce5156ba6085e00a9d54fead6ed29a9c47e215cd1bba2e976ef39f5710a76", size = 9516, upload-time = "2025-10-23T09:00:20.675Z" },
|
{ url = "https://files.pythonhosted.org/packages/af/33/ee4519fa02ed11a94aef9559552f3b17bb863f2ecfe1a35dc7f548cde231/matplotlib_inline-0.2.1-py3-none-any.whl", hash = "sha256:d56ce5156ba6085e00a9d54fead6ed29a9c47e215cd1bba2e976ef39f5710a76", size = 9516, upload-time = "2025-10-23T09:00:20.675Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mdurl"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "openpyxl"
|
name = "openpyxl"
|
||||||
version = "3.1.5"
|
version = "3.1.5"
|
||||||
@ -832,6 +853,7 @@ dependencies = [
|
|||||||
{ name = "pillow" },
|
{ name = "pillow" },
|
||||||
{ name = "psycopg2-binary" },
|
{ name = "psycopg2-binary" },
|
||||||
{ name = "redis" },
|
{ name = "redis" },
|
||||||
|
{ name = "rich" },
|
||||||
{ name = "reportlab" },
|
{ name = "reportlab" },
|
||||||
{ name = "whitenoise" },
|
{ name = "whitenoise" },
|
||||||
]
|
]
|
||||||
@ -866,6 +888,7 @@ requires-dist = [
|
|||||||
{ name = "pytest-cov", marker = "extra == 'dev'", specifier = ">=4.1.0" },
|
{ name = "pytest-cov", marker = "extra == 'dev'", specifier = ">=4.1.0" },
|
||||||
{ name = "pytest-django", marker = "extra == 'dev'", specifier = ">=4.7.0" },
|
{ name = "pytest-django", marker = "extra == 'dev'", specifier = ">=4.7.0" },
|
||||||
{ name = "redis", specifier = ">=5.0.0" },
|
{ name = "redis", specifier = ">=5.0.0" },
|
||||||
|
{ name = "rich", specifier = ">=14.2.0" },
|
||||||
{ name = "reportlab", specifier = ">=4.4.7" },
|
{ name = "reportlab", specifier = ">=4.4.7" },
|
||||||
{ name = "ruff", marker = "extra == 'dev'", specifier = ">=0.1.0" },
|
{ name = "ruff", marker = "extra == 'dev'", specifier = ">=0.1.0" },
|
||||||
{ name = "whitenoise", specifier = ">=6.6.0" },
|
{ name = "whitenoise", specifier = ">=6.6.0" },
|
||||||
@ -1050,6 +1073,19 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738, upload-time = "2025-08-18T20:46:00.542Z" },
|
{ url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738, upload-time = "2025-08-18T20:46:00.542Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rich"
|
||||||
|
version = "14.2.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "markdown-it-py" },
|
||||||
|
{ name = "pygments" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/fb/d2/8920e102050a0de7bfabeb4c4614a49248cf8d5d7a8d01885fbb24dc767a/rich-14.2.0.tar.gz", hash = "sha256:73ff50c7c0c1c77c8243079283f4edb376f0f6442433aecb8ce7e6d0b92d1fe4", size = 219990, upload-time = "2025-10-09T14:16:53.064Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/25/7a/b0178788f8dc6cafce37a212c99565fa1fe7872c70c6c9c1e1a372d9d88f/rich-14.2.0-py3-none-any.whl", hash = "sha256:76bc51fe2e57d2b1be1f96c524b890b816e334ab4c1e45888799bfaab0021edd", size = 243393, upload-time = "2025-10-09T14:16:51.245Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rpds-py"
|
name = "rpds-py"
|
||||||
version = "0.30.0"
|
version = "0.30.0"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user