
    Pi;X                       d Z ddlmZ ddlZddlmZ ddlmZ ddlm	Z	m
Z
 ddgd	  ed
d          D             z   Z eh d          Z eh d          Z eh d          Z eh d          Z eh d          Z G d de          Z G d dej                  Zd-d.dZd/d Z eh d!          Z eh d"          Zd0d'Zd1d(Zd2d,ZdS )3a  
Python command handler for Dippy.

Analyzes Python scripts to determine if they're safe (read-only, no I/O,
no code execution). Uses AST-based static analysis with a whitelist approach.

Conservative by design: if we can't prove it's safe, ask for confirmation.
    )annotationsN)Path)
NamedTuple)ClassificationHandlerContextpythonpython3c                    g | ]}d | S )zpython3. ).0vs     1/root/projects/gits/Dippy/src/dippy/cli/python.py
<listcomp>r      s    #I#I#IqNqNN#I#I#I          >9   html.parserhtml.entitiescollections.abcreuuabcastcsvdiscopyenumhmachtmljsonmathtimezlibarraycmathheapqtokentypesbase64bisectpprintquoprirandomstringstructtypingdecimaldifflibhashlibkeywordnumbersreprlibtomllibbinasciicalendardatetimegraphliboperatorsymtabletextwraptokenizewarningszoneinfo	fractions	functools	itertools	traceback
contextlib
statisticscollectionsdataclassesunicodedatatyping_extensions>_   xml.domxml.sax	xml.etreehttp.clienthttp.serverxml.parsersurllib.parseurllib.requestxml.dom.minidomxml.dom.pulldomwsgiref.handlersxml.parsers.expatconcurrent.futuresxml.dom.expatbuilderxml.etree.ElementTreexml.etree.cElementTreegcioosbz2cgicmddbmgrpptypwdsslsysttyxmlcodedillglobgziphttplzmammapspwdcgitbcryptfcntlrunpyshlexatexitcodecscodeopctypesftplibgetoptpicklepopen2poplibshelveshutilsignalsocketurllibxmlrpcasynciocPicklefnmatchgetpassimaplibinspectloggingmarshalnntplibpathlibpkgutilsmtplibsqlite3tarfiletermioszipfileargparsecommandsplatformresourcetempfile	fileinput	importlib	ipaddress	linecache	sysconfig	telnetlib	threading
compileall
concurrent
jsonpickle
py_compile
subprocess
webbrowserconfigparsersocketservermultiprocessing>   direvalexecopenvarsinputprintlocalscompiledelattrgetattrglobalssetattr
__import__
breakpoint
memoryview>4   idabsallanybinchrhexintlenmapmaxminoctordpowsetstrsumzipbooldicthashiterlistnextreprtypeasciibytesfloatrangeroundslicesupertupledivmodfilterformatobjectsortedcomplexhasattrcallablepropertyreversed	bytearray	enumerate	frozenset
isinstance
issubclassclassmethodstaticmethod>p   runbindcallr   forkkilllinkr   readrecvsendwaitPopenchmodchowncloseexeclexecvflushmkdirpopenrmdirspawnwait3wait4writeacceptchrootexecleexeclpexecveexecvpf_backf_codekillpglistenr~   popen3popen4removerenamermtreesendtospawnlspawnvsystemunlink__mro__co_codeconnectcr_codeexeclpeexecvpef_traceforkptygi_coderecvmsgreplacerequestsendallsendmsgspawnlespawnlpspawnvespawnvpsymlinktb_nexturlopenwaitpid__code____dict____spec__cr_awaitcr_framef_localsgi_framemakedirsreadlinerecvfromspawnlpespawnvpetb_frametruncate	Unpickler	__bases__	__class__	f_globals	getoutput	read_text	readlines	startfile	terminater   
__loader__
__reduce__
check_call
f_builtins
read_bytes
write_text
writelines__closure____globals__urlretrievewrite_bytes__builtins____getstate____setstate__check_outputgi_yieldfrom__reduce_ex____subclasses__getstatusoutputc                  <    e Zd ZU dZded<   ded<   ded<   ded<   dS )		Violationz)A safety violation found during analysis.r   linecolr   kinddetailN)__name__
__module____qualname____doc____annotations__r   r   r   r\  r\    s:         33IIIHHHIIIKKKKKr   r\  c                      e Zd ZdZd(d)dZd*dZd+dZd,dZd-dZ e	h d          Z
d.dZd/dZd0dZd1dZd2dZd3d Zd4d"Zd5d$Zd6d&Zd'S )7SafetyAnalyzerz
    AST visitor that checks Python code for safety.

    Uses a strict whitelist approach: only explicitly safe constructs
    are allowed. Anything unknown is flagged.
    Tallow_printr   c                "    g | _         || _        d S N)
violationsrh  )selfrh  s     r   __init__zSafetyAnalyzer.__init__  s    +-&r   nodeast.ASTr_  r   r`  returnNonec           
         | j                             t          t          |dd          t          |dd          ||                     d S )Nlinenor   
col_offset)rk  appendr\  r   )rl  rn  r_  r`  s       r   _addzSafetyAnalyzer._add  sU    h**GD,,J,JDRX 	
 	
 	
 	
 	
r   
ast.Importc                :   |j         D ]}}|j        }|                    d          d         }|t          v s	|t          v r|                     |dd|            Q|t
          vr#|t
          vr|                     |dd|            ~|                     |           d S )N.r   importdangerous module: unknown module: )namesnamesplitDANGEROUS_MODULESrv  SAFE_MODULESgeneric_visit)rl  rn  aliasmoduleroots        r   visit_ImportzSafetyAnalyzer.visit_Import  s    Z 	G 	GEZF<<$$Q'D***d6G.G.G		$*Gv*G*GHHHH|++L0H0H		$*EV*E*EFFF4     r   ast.ImportFromc                f   |j         |                     |dd           d S |j         }|                    d          d         }|t          v s	|t          v r|                     |dd|            n,|t          vr#|t          vr|                     |dd|            |                     |           d S )Nrz  zrelative import without modulery  r   r{  r|  )r  rv  r  r  r  r  )rl  rn  r  r  s       r   visit_ImportFromzSafetyAnalyzer.visit_ImportFrom  s    ;IIdH&FGGGF||C  #&&&$2C*C*CIIdH&C6&C&CDDDD<''D,D,DIIdH&A&A&ABBB4     r   ast.Callc                   |j         }t          |t          j                  r^|j        }|t
          v r)|dk    r| j        rn|                     |dd|            ni|t          vr|d         	                                s	 nDt          |t          j
                  r*|j        }|t          v r|                     |dd|            |                     |           d S )Nr   builtinzdangerous builtin: r   methodzdangerous method: )funcr   r   Namer   DANGEROUS_BUILTINSrh  rv  SAFE_BUILTINSisupper	AttributeattrDANGEROUS_ATTRSr  )rl  rn  r  r~  r  s        r   
visit_CallzSafetyAnalyzer.visit_Call  s    y dCH%% 	G7D)))7??t'7?IIdI/KT/K/KLLLL]**47??3D3D*  cm,, 	G9D&&		$*Et*E*EFFF4     r   >   r  r  r  r  r  r!  r#  r.  r1  r2  r4  r5  r6  r7  r=  r@  rA  rB  rI  rK  rO  rP  rS  rW  rX  rY  ast.Attributec                    |j         | j        v r|                     |dd|j                     |                     |           d S )N
reflectionzdangerous attribute: )r  REFLECTION_ATTRSrv  r  rl  rn  s     r   visit_AttributezSafetyAnalyzer.visit_Attribute1  sM    9---IIdL*M$)*M*MNNN4     r   ast.Namec                z    |j         }|dv r|                     |dd|            |                     |           d S )N)rS  rH  r3  r  zdangerous name: )r   rv  r  )rl  rn  r~  s      r   
visit_NamezSafetyAnalyzer.visit_Name8  sN    w===IIdL*CT*C*CDDD4     r   ast.Starredc                0    |                      |           d S rj  r  r  s     r   visit_StarredzSafetyAnalyzer.visit_Starred@      4     r   ast.FunctionDefc                    |j         D ]+}t          |t          j                  r|j        t
          vr	 ,|                     |           d S rj  )decorator_listr   r   r  r   r  r  )rl  rn  	decorators      r   visit_FunctionDefz SafetyAnalyzer.visit_FunctionDefD  sS    , 	 	I)SX.. <}444     r   ast.AsyncFunctionDefc                ^    |                      |dd           |                     |           d S )Nasynczasync functions require asynciorv  r  r  s     r   visit_AsyncFunctionDefz%SafetyAnalyzer.visit_AsyncFunctionDefM  s3    		$!BCCC4     r   	ast.Awaitc                ^    |                      |dd           |                     |           d S )Nr  zawait requires asyncior  r  s     r   visit_AwaitzSafetyAnalyzer.visit_AwaitR  s3    		$!9:::4     r   ast.Withc                   |j         D ]i}|j        }t          |t          j                  rFt          |j        t          j                  r'|j        j        dk    r|                     |dd           j| 	                    |           d S )Nr   r]   zfile open in with statement)
itemscontext_exprr   r   Callr  r  r   rv  r  )rl  rn  itemctxs       r   
visit_WithzSafetyAnalyzer.visit_WithV  s     J 	M 	MD#C#sx(( Mch11 Mx{f,,		$.KLLL4     r   
ast.Globalc                    d S rj  r   r  s     r   visit_GlobalzSafetyAnalyzer.visit_Globala  s    r   ast.Tryc                0    |                      |           d S rj  r  r  s     r   	visit_TryzSafetyAnalyzer.visit_Trye  r  r   NT)rh  r   )rn  ro  r_  r   r`  r   rp  rq  )rn  rw  rp  rq  )rn  r  rp  rq  )rn  r  rp  rq  )rn  r  rp  rq  )rn  r  rp  rq  )rn  r  rp  rq  )rn  r  rp  rq  )rn  r  rp  rq  )rn  r  rp  rq  )rn  r  rp  rq  )rn  r  rp  rq  )rn  r  rp  rq  )ra  rb  rc  rd  rm  rv  r  r  r  r   r  r  r  r  r  r  r  r  r  r  r   r   r   rg  rg    s_        ' ' ' ' '
 
 
 

! 
! 
! 
!! ! ! !! ! ! !4 !y	
 	
 	
! !F! ! ! !! ! ! !! ! ! !! ! ! !! ! ! !
! ! ! !	! 	! 	! 	!   ! ! ! ! ! !r   rg  Tsourcer   rh  r   rp  list[Violation]c           	        	 t          j        |           }nE# t          $ r8}t          |j        pd|j        pddt          |                    gcY d}~S d}~ww xY wt          |          }|                    |           |j	        S )zx
    Analyze Python source code for safety violations.

    Returns list of violations, empty if code appears safe.
    r   syntaxN)rh  )
r   parseSyntaxErrorr\  rs  offsetr   rg  visitrk  )r  rh  treeeanalyzers        r   analyze_python_sourcer  j  s    Ky   K K K!(-aQ#a&&IIJJJJJJJK +666HNN4s    
A-AAApathr   tuple[bool, str]c                   |                                  sdd|  fS |                                 sdd|  fS | j        dvrdd| j         fS 	 |                                 j        }|dk    rdS n# t
          $ r}dd| fcY d	}~S d	}~ww xY w	 |                     d
          }n%# t
          t          f$ r}dd| fcY d	}~S d	}~ww xY wt          |          }|r$|d         }d|j	         d|j
         d|j         dfS dS )zK
    Analyze a Python file for safety.

    Returns (is_safe, reason).
    Fzfile not found: znot a file: )z.pyz.pywznot a Python file: i )Fzfile too large to analyzezcannot stat file: Nzutf-8)encodingzcannot read file: r   : z (line ))Tzstatic analysis passed)existsis_filesuffixstatst_sizeOSErrorrD  UnicodeDecodeErrorr  r_  r`  r]  )r  sizer  r  rk  r   s         r   analyze_python_filer  z  s    ;;== 0/////<<>> ,+T++++ {/))9DK9999/yy{{"'>>55  / / /.1.........//11'( / / /.1........./ 'v..J >qM==18==AF=====))s<   A/ /
B
9B?B
B
B% %C6C<CC>   -W-X--check-hash-based-pycs-c-m>   -V-h-VV--help	--versiontokens	list[str]cwdtuple[Path | None, int]c                p   d}|t          |           k     r| |         }|t          v rdS |dv rdS |t          v r|dz  };|                    d          r
d|v r|dz  }Z|                    d          r|dz  }ut	          |          }|                                s||z  }|                                |fS dS )zu
    Find the script path in Python command tokens.

    Returns (path, index) or (None, -1) if no script found.
       )N)r  r     -=)r   
SAFE_FLAGSFLAGS_WITH_ARG
startswithr   is_absoluteresolve)r  r  ir'   script_paths        r   _find_script_pathr    s     	
A
c&kk//q	 J8 L  8 N""FA C   	SE\\FA C   	FA 5kk&&(( 	,+K""$$a''8r   c                   t          |           dk     r| d         S | dd         D ]}|t          v r| d          d| c S |dk    r| d          dc S |dk    rP|                     d          }|dz   t          |           k     r| d          d	| |dz             c S | d          d
c S |                    d          s!| d          dt	          |          j         c S | d         S )z#Get description for Python command.r  r   r  N r  z -cr  z -m z -mr  )r   r  indexr  r   r~  )r  r'   idxs      r   get_descriptionr    s9   
6{{Qay 5 5JQi))%)))))D==Qi$$$$$$D==,,t$$CQwV$$ )::a:::::Qi$$$$$$$$ 	5Qi44$u++"244444	5 !9r   r  r   r   c                   | j         }t          j                    }t          |          }t	          |          dk     rt          d|d          d          S |dd         D ]}|t          v rt          d|          c S d	|v rt          d|          S d
|v r^|                    d
          }|dz   t	          |          k     r"||dz            }|dk    rt          d|          S t          d|          S d|v rt          d|          S t          ||          \  }}|t          d|          S t          |          \  }	}
|	rt          d| d          S t          d| d|
           S )a6  Classify Python command for approval.

    Auto-approves:
    - Version/help flags
    - Scripts that pass static analysis (no I/O, no dangerous imports)

    Requires confirmation:
    - -c (inline code)
    - -m (module execution)
    - Scripts that fail analysis or can't be read
    - Interactive mode
    r  askr   z interactive)descriptionr  Nallowr  r  r9   z-iz (analyzed)r  )
r  r   r  r  r   r   r  r  r  r  )r  r  r  descr'   r  r  r  _is_safereasons              r   classifyr    s    ZF
(**C6""D
6{{QeF1I1K1K1KLLLL  = =J!'t<<<<<<  v~~e6666 v~~ll4  7S[[  C!G_F
 ##%g4@@@@e6666 v~~e6666 'vs33NKe6666 *+66OGV Fgd3G3G3GHHHH eD1D1DF1D1DEEEEr   r  )r  r   rh  r   rp  r  )r  r   rp  r  )r  r  r  r   rp  r  )r  r  rp  r   )r  r   rp  r   )rd  
__future__r   r   r   r   r0   r   	dippy.clir   r   r   COMMANDSr   r  r  r  r  r  r\  NodeVisitorrg  r  r  r  r  r  r  r  r   r   r   <module>r
     sm    # " " " " " 



             4 4 4 4 4 4 4 4i #I#IEE!RLL#I#I#II yL L LN Nd Im m mo o d Y    8 	< < <> >D )~ ~ ~@ @F    
   a! a! a! a! a!S_ a! a! a!H     %* %* %* %*V     Y   
( ( ( (V   ,>F >F >F >F >F >Fr   