o
    _�¿j  ã                   @  s¾   d Z ddlmZ ddlZddlZddlZddlmZmZ ddl	m
Z ddlmZmZmZmZ er6ddlmZ e d¡Zddd„Zdedfddd„Zdedfddd„ZG dd„ dƒZg d¢ZdS )um  HTTP session management â€” creation, warm-up, and proxy rotation.

Key improvements over original:
- Session is created ONCE per fetch operation, not once per retry attempt.
- Warm-up failures are non-fatal and don't create new sessions.
- Proxy rotation is deterministic (round-robin) not purely random.
- Sessions are properly closed when context manager exits.
é    )ÚannotationsN)ÚTYPE_CHECKINGÚAny)Úrequests)ÚDEFAULT_WARMUP_TIMEOUT_SÚNSE_BASE_URLÚNSE_WARMUP_URLSÚUSER_AGENTS)ÚSettingszindiaopt.sessionÚ
proxy_urlsú	list[str]Úreturnúdict[str, str] | Nonec                 C  s   | sdS t  | ¡}||dœS )zÎReturn a randomly selected proxy dict, or ``None`` if no proxies configured.

    Args:
        proxy_urls: List of proxy URL strings.

    Returns:
        ``{"http": url, "https": url}`` or ``None``.
    N)ÚhttpÚhttps)ÚrandomÚchoice)r   Úurl© r   úP/home/dinkstrade/pdmp/venv/lib/python3.10/site-packages/indiaopt/http/session.pyÚ
pick_proxy    s   	

r   Túlist[str] | NoneÚwarmup_timeoutÚfloatÚwarmupÚboolr   c                 C  sÄ   t jdd�}|j t t¡dddt› d�dddd	œ¡ | r)t| ƒ}|r)|j	 |¡ |r`t
D ]2}z|j||d
�}t d||j¡ W n tyY } zt d||¡ W Y d}~nd}~ww t d¡ q-|S )aé  Create and warm up an NSE-compatible curl_cffi session.

    Performs two GET requests to NSE's landing pages so that the session
    accumulates the cookies NSE requires for API calls.

    Args:
        proxy_urls:      Optional list of proxy URLs to rotate over.
        warmup_timeout:  Timeout for each warm-up request in seconds.
        warmup:          Set to ``False`` to skip warm-up (e.g. in tests).

    Returns:
        A ready-to-use :class:`curl_cffi.requests.Session`.
    Ú	chrome124©Úimpersonateú!application/json, text/plain, */*úen-US,en;q=0.9zgzip, deflate, brz/option-chainú
keep-alivezno-cache)ú
User-AgentÚAcceptúAccept-LanguagezAccept-EncodingÚRefererÚ
ConnectionzCache-ControlÚPragma©Útimeoutu   Warm-up GET %s â†’ HTTP %dz,Warm-up request to %s failed (non-fatal): %sNg333333Ó?)Úcffi_requestsÚSessionÚheadersÚupdater   r   r	   r   r   Úproxiesr   ÚgetÚloggerÚdebugÚstatus_codeÚ	ExceptionÚtimeÚsleep)r   r   r   Úsessionr.   r   ÚrespÚexcr   r   r   Úcreate_nse_session/   s:   øÿÿ€þr9   c              
   C  s²   ddl m} tjdd�}|j t t¡dd|ddœ¡ | r)t	| ƒ}|r)|j
 |¡ |rWz|j||d	�}t d
||j¡ W |S  tyV } zt d|¡ W Y d}~|S d}~ww |S )a)  Create a BSE-compatible curl_cffi session.

    Args:
        proxy_urls:     Optional list of proxy URLs.
        warmup_timeout: Timeout for warm-up requests.
        warmup:         Set to ``False`` to skip warm-up.

    Returns:
        A ready-to-use :class:`curl_cffi.requests.Session`.
    r   )ÚBSE_BASE_URLr   r   r   r    r!   )r"   r#   r$   r%   r&   r(   u   BSE warm-up GET %s â†’ HTTP %dz"BSE warm-up failed (non-fatal): %sN)Úindiaopt.constantsr:   r*   r+   r,   r-   r   r   r	   r   r.   r/   r0   r1   r2   r3   )r   r   r   r:   r6   r.   r7   r8   r   r   r   Úcreate_bse_sessionc   s2   ûÿ
ý€ýr<   c                   @  sN   e Zd ZdZddd„Zddd	„Zddd„Zedddd„ƒZedddd„ƒZ	dS )ÚSessionManagerzçContext manager that owns a session lifetime.

    Ensures the session is properly closed even if an exception occurs::

        with SessionManager.for_nse(settings) as session:
            resp = session.get(url, timeout=15)
    r6   r   r   ÚNonec                 C  s
   || _ d S ©N©Ú_session)Úselfr6   r   r   r   Ú__init__—   s   
zSessionManager.__init__c                 C  s   | j S r?   r@   )rB   r   r   r   Ú	__enter__š   s   zSessionManager.__enter__Ú_Úobjectc                 G  s&   z| j  ¡  W d S  ty   Y d S w r?   )rA   Úcloser3   )rB   rE   r   r   r   Ú__exit__�   s
   ÿzSessionManager.__exit__NÚsettingsúSettings | Nonec                 C  ó0   |r|j ng }|r|jnt}t||d�}| |ƒS )z<Create a :class:`SessionManager` with an NSE-warmed session.©r   r   )r   r   r   r9   ©ÚclsrI   r   r   r6   r   r   r   Úfor_nse£   ó   þzSessionManager.for_nsec                 C  rK   )z;Create a :class:`SessionManager` with a BSE-warmed session.rL   )r   r   r   r<   rM   r   r   r   Úfor_bse®   rP   zSessionManager.for_bse)r6   r   r   r>   )r   r   )rE   rF   r   r>   r?   )rI   rJ   r   r=   )
Ú__name__Ú
__module__Ú__qualname__Ú__doc__rC   rD   rH   ÚclassmethodrO   rQ   r   r   r   r   r=   Ž   s    



r=   )r=   r<   r9   r   )r   r   r   r   )r   r   r   r   r   r   r   r   )rU   Ú
__future__r   Úloggingr   r4   Útypingr   r   Ú	curl_cffir   r*   r;   r   r   r   r	   Úindiaopt.config.settingsr
   Ú	getLoggerr0   r   r9   r<   r=   Ú__all__r   r   r   r   Ú<module>   s,    	

ý5ý+,