
    5iE                        d Z ddlmZmZmZmZ ddlZddlZddlZddl	Z	ddl
Z
ddlZddlZddlZddlZddlZddlmZ ddlmZ ddlZddlZddlmZ i Zdaej4                  ej6                  z   ej8                  z   ej:                  z   Zd Zd	 Z dd
Z!ddZ"d Z#d Z$d Z% G d dejL                        Z' G d de      Z( G d de)      Z*y)zH
Utilities used in the DNAnexus execution environment and test harness.
    )print_functionunicode_literalsdivisionabsolute_importN)Mapping)wraps   )AppInternalErrorc                     t        |       S )zw
    Returns an equivalent unicode object, trying harder to avoid
    dependencies on the Python default encoding.
    )str)os    w/home/marpiech/ifpan-abm-pgxpred/analysis/marpiech-gwas-test/venv/lib/python3.12/site-packages/dxpy/utils/exec_utils.py_safe_unicoder   %   s    
 q6M    c                     t        | t        j                        rt        |       S | j                  j
                  dz   t        |       z   S )z*
    Formats the specified exception.
    z: )
isinstancedxpyAppErrorr   	__class____name__)es    r   _format_exception_messager   ,   s<     !T]]#Q;;$&q)999r   c                    t         dz  a t        j                         }t        j                  nt        j                          	 t        j                         j                  t        j                                t        j                  t        j                        }nS|  t        j                  j                  dd      } |*t!        dd      5 }t#        j$                  |      }ddd       | |d}t!        d	d
      5 }|j'                  dddz  z          ddd       t        d|j                  d      d|j                  d             	 t)        |d      di |d   }|Zt        j0                  |       t!        dd
      5 }t#        j2                  ||dt4               |j'                  d       ddd       |S |S # t        j                  j                  $ r t        d       Y mw xY w# 1 sw Y   	xY w# 1 sw Y   xY w# t        j*                  $ r}t-        ||d        d}~wt.        $ r}t-        ||        d}~ww xY w# 1 sw Y   |S xY w)a  Triggers the execution environment entry point processor.

    Use this function in the program entry point code:

    .. code-block:: python

       import dxpy

       @dxpy.entry_point('main')
       def hello(i):
           pass

       dxpy.run()

    This method may be used to invoke the program either in a production
    environment (inside the execution environment) or for local
    debugging (in the debug harness), as follows:

    If the environment variable *DX_JOB_ID* is set, the processor
    retrieves the job with that ID from the API server. The job's
    *function* field indicates the function name to be invoked. That
    function name is looked up in the table of all methods decorated
    with *@dxpy.entry_point('name')* in the module from which
    :func:`run()` was called, and the matching method is invoked (with
    the job's input supplied as parameters). This is the mode of
    operation used in the DNAnexus execution environment.

    .. warning::

       The parameters *function_name* and *function_input* are
       disregarded in this mode of operation.

    If the environment variable *DX_JOB_ID* is not set, the function
    name may be given in *function_name*; if not set, it is set by the
    environment variable *DX_TEST_FUNCTION*. The function input may be
    given in *function_input*; if not set, it is set by the local file
    *job_input.json* which is expected to be present.

    The absence of *DX_JOB_ID* signals to :func:`run()` that execution
    is happening in the debug harness. In this mode of operation, all
    calls to :func:`dxpy.bindings.dxjob.new_dxjob()` (and higher level
    handler methods which use it) are intercepted, and :func:`run()` is
    invoked instead with appropriate inputs.

       NzATODO: FIXME: the EE client should die if logging is not availableDX_TEST_FUNCTIONmainzjob_input.jsonr)functioninputjob_error_reserved_spacewz^This file contains reserved space for writing job errors in case the filesystem becomes full.
a                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   @   Invokingr   withr   r   )
error_typezjob_output.jsonr	   )indentcls
 )	RUN_COUNTosgetcwdr   JOB_IDloggingbasicConfig	getLogger
addHandlerDXLogHandler
exceptionsDXErrorprintdescribeenvirongetopenjsonloadwriteENTRY_POINT_TABLEr   
save_error	ExceptionchdirdumpDXJSONEncoder)function_namefunction_inputdx_working_dirjobfhresultr   s          r   runrI   7   s   ` NIYY[N{{	W**4+<+<+>? mmDKK( JJNN+=vFM!&, /!%2/ )>B	(#	. B"
ru}  A  vA  A  	BB 
*cggj)637773CD"3z?3Cc'lC 
 #S) 	R		&"QMB	 M6ME && 	WUV	W/ /
B B == 1n< 1n%	 MsZ   5F: G);G6H ?/I:(G&%G&)G36G?IH$$I0H==IIc                 6   t         j                  vt        j                  |       	 t        j                  d       t        dd      5 }t        j                  d|t        |       di|       |j                  d       d d d        y y #  Y PxY w# 1 sw Y   y xY w)Nr    zjob_error.jsonr!   error)typemessager(   )
r   r-   r+   r@   unlinkr9   r:   rA   r   r<   )r   working_dirr%   rG   s       r   r>   r>      s    {{
	II01 "C( 	B		7ZD]^_D`$abdfg	 	 		 	s   B 6BBBc                 L   t        | t        j                        rt        j                  |       } | S t        | t              r(| j                         D ]  \  }}t        |      | |<    | S t        | t              r*t        t        |             D ]  }t        | |         | |<    | S N)
r   r   DXObjectdxlinkr   itemsconvert_handlers_to_dxlinkslistrangelen)xkeyvalueis       r   rU   rU      s    !T]]#KKN H 
Aw	'') 	8JC07AcF	8
 H 
At	s1v 	5A.qt4AaD	5Hr   c                    t        j                         }t               }|j                  dg       D ]  }i }|j                  d      dk(  r
t        |d<   nd|j                  d      dk(  r
t
        |d<   nF|j                  d      dk(  r
t        |d<   n(|j                  d      dk7  r|j                  |d          |j                  d      d k7  r	|d    |d	<    |j                  d
|d   z   fi |  i }t        |j                  |             j                         D ]+  \  }}|	||v r	 t        j                  |      ||<   '|||<   - |S # t        $ rs ddlm}	  |	|dddid      \  }
}}t#        |
||       |t%        |      dk7  rt        dj'                  |            t)        j*                  |d   d   |
      ||<   Y w xY w)N	inputSpecrL   intfloatbooleanstringnameoptionalrequiredz--r   )resolve_existing_pathFidT)ask_to_resolver6   
allow_multr   zValue {v} could not be resolved)v)
project_id)argparseArgumentParsersetr8   r_   r`   booladdadd_argumentvars
parse_argsrT   r:   loads
ValueErrordxpy.utils.resolverrf   r5   rX   formatr   rS   )argsapp_specparserjson_inputsispeckwargsinputsr\   r[   rf   projectpathresultss                r   parse_args_as_job_inputr      s   $$&F%Kk2. <99V% F6NYYv')"F6NYYv)+!F6NYYv(*OOE&M*99Z D(%*:%6!6F:D5=0;F;<  F**401779 5=N JJu-q	 F1I  M  NE)>uUZfjlpeq  D  *E&wgtW-?c'la&7$%F%M%MPU%M%VWW KK
4(8WMq	Ns   (E

A9GGc                       fd}|S )zUse this to decorate a DNAnexus execution environment entry point.

    Example:

    .. code-block:: python

       @dxpy.entry_point('main')
       def hello(i):
           pass

    c                 B      t         <   t                fd       }|S )Nc                       | i |S rQ   r)   )rx   r}   fs     r   	wrapped_fz,entry_point.<locals>.wrap.<locals>.wrapped_f   s    d%f%%r   )r=   r   )r   r   entry_point_names   ` r   wrapzentry_point.<locals>.wrap   s+    ./*+	q	& 
	&r   r)   )r   r   s   ` r   entry_pointr      s     Kr   c                       e Zd ZdZd Zy)rB   zL
    Like json.JSONEncoder, but converts DXObject objects into dxlinks.
    c                     t        |t        j                        rt        j                  |      S t        j
                  j                  | |      S rQ   )r   r   rR   rS   r:   JSONEncoderdefault)selfobjs     r   r   zDXJSONEncoder.default   s8    c4==);;s##''c22r   N)r   
__module____qualname____doc__r   r)   r   r   rB   rB      s    3r   rB   c                       e Zd Zy)DXExecDependencyErrorN)r   r   r   r)   r   r   r   r      s    r   r   c                   T    e Zd ZdZdZddZd Zd Zd ZddZ	d	 Z
d
 Zd Zd Zd Zy)DXExecDependencyInstallera(  
    Installs dependencies specified by the job.

    Dependencies are processed in the order specified in the
    bundledDepends, execDepends, and dependencies arrays of the
    runSpec hash (the former two are deprecated). Neighboring package
    dependencies of the same type are grouped.
    )aptgemcpancranpippip3Nc                    d|vrt        d      d|d   v rd|vrt        d      || _        |d   | _        || _        | j                  j	                  dd      | _        || _        g | _        t        j                  | j                         | j                  j	                  dg       | j                  j	                  d	g             D ]  }| j                  |       | j                  |      }|d
   dv r|dk(  r3d|v r@| j
                  |d   vr/| j                  dj                  |d
   | j
                               wt        | j                        dk(  s#| j                  d   d   |k7  s|| j                   vr2| j                  j#                  |g t        | j                        d       | j                  d   d   j#                  |        y)a  
        :param executable_desc: The description of the executable of
            this job, which can be obtained in the response of the
            /executable-x/describe request. This dict must contain the
            following keys:
                - "runSpec"
        :type executable_desc: dict
        :param job_desc: The description of this job, which can be
            obtained in the response of the /job-x/describe request.
            If ``executable_desc["runSpec"]`` has key
            "bundledDependsByRegion", then this dict must contain the
            following keys:
                - "region"
        :type job_desc: dict
        runSpeczAExpected field "runSpec" to be present in executable description"bundledDependsByRegionregionz(Expected key 'region' in job descriptionr   r   execDependsdependenciesrc   )z
dx-toolkitjqzpython-argcompleter   stageszDSkipping dependency {} because it is inactive in stage (function) {}r   rL   )rL   depsindexr   N)r   	exec_descrun_specjob_descr8   stagelogger
dep_groups	itertoolschain_get_local_bundled_dependencies_validate_dependency_get_dependency_typelogrw   rX   	group_pmsappend)r   executable_descr   r   depdep_types         r   __init__z"DXExecDependencyInstaller.__init__   s     O+'(kll#y'AAhV^F^'(RSS('	2 ]]&&z6:
??4#G#G#I#'==#4#4]B#G#'==#4#4^R#HJ 	4C %%c*005H 6{HHXY^M^34::S]#B_ffgjkqgrgkgqgqs t 4??#q(DOOB,?,G8,SW_gkguguWu&&"sSWSbSbOc'deOOB'..s3'	4r   c                     | j                   j                  d      }|| j                   j                  dg       S | j                  d   }||   S )Nr   bundledDependsr   )r   r8   r   )r   bundled_depends_by_region
job_regions      r   r   z9DXExecDependencyInstaller._get_local_bundled_dependencies/  sQ    $(MM$5$56N$O!$,==$$%5r:: x0J,Z88r   c                 j    | j                   r| j                   j                  |       y t        |       y rQ   )r   infor5   )r   rM   s     r   r   zDXExecDependencyInstaller.log8  s"    ;;KKW%'Nr   c                    d}d}d}d}|j                  |||      }d;d}|d   |d   }	}|d	k(  r|j                   ||	      
      S |dk(  rd ||	d      z   S |dk(  rd ||	d      z   S |dk(  rWg }
|	D ]1  }|
j                  d|d   z          d|v s|
dxx   d|d   z   z  cc<   3 dj                  t        t        |
            S |dk(  rd ||	d      z   S |dk(  rd}d}|dj                  |      z  }d }d!}g }
|	D ]O  }d|v r d"j                   d<i |}nd#j                  |d         }|
j                  |j                  ||$             Q t        d% |
D              r#|
j                  d&|j                  ||$             dj                  |
      S |d'k(  rSd(d)g}
|	D ]8  }g }t	        |j                  d*d+            }|j                  d,|z         |j                  d-|z         |j                  d.t	        |d/         z          t        j                  d0t	        |d/               j                  d1      }|j                  d2      r|d t        d2        }|j                  d3|z         d4|v r |j                  d5t	        |d4         z          d6|v r|j                  t	        |d6                |
j                  d7dj                  |      z   d8z          ; dj                  |
      S t        d9j                  |:            )=NzZexport DEBIAN_FRONTEND=noninteractive && apt-get install --yes --no-install-recommends {p}zyapt-get update -o Dir::Etc::sourcelist=sources.list.d/nucleus.list -o Dir::Etc::sourceparts=- -o APT::Get::List-Cleanup=0zIAPT failed, retrying with full update against official package repositoryz<({dx_upd} && {inst}) || (echo {e}; apt-get update && {inst}))dx_updinstr   c                 X    fd| D        }dj                  t        t        |            S )Nc              3   F   K   | ]  }|d    d|v r|d   z   ndz     yw)rc   version Nr)   ).0pversion_separators     r   	<genexpr>zVDXExecDependencyInstaller.generate_shellcode.<locals>.make_pm_atoms.<locals>.<genexpr>G  s/     vhiQvYIYZN*;AiL*H`bcvs   ! )joinmapr   )packagesr   package_atomss    ` r   make_pm_atomszCDXExecDependencyInstaller.generate_shellcode.<locals>.make_pm_atomsF  s$    vmuvM88C]344r   rL   r   r   )r   r   zpip install --upgrade z==)r   r   zpip3 install --upgrade r   zgem install rc   r   r   z --version z && r   zcpanm --notest ~r   zhttp://cloud.r-project.orgzGdie <- function() { q(status=1) }; options(error=die); options(warn=2);z?r <- getOption("repos"); r["CRAN"] = "{repo}"; options(repos=r))repozR -e '{preamble}; {cmd}'zinstall.packages("devtools")zArequire(devtools); install_version("{name}", version="{version}")zinstall.packages("{}"))preamblecmdc              3   $   K   | ]  }d |v  
 yw)zrequire(devtools)Nr)   )r   r   s     r   r   z?DXExecDependencyInstaller.generate_shellcode.<locals>.<genexpr>g  s     B#&#-Bs   r   gitzapt-get install --yes git makez export GIT_SSH=dx-git-ssh-helperdestdirz$(mktemp -d)zmkdir -p %szcd %sz
git clone urlz	([^\/]+)$r   z.gitzcd '%s'tagzgit checkout build_commands()z'Package manager type {pm} not supported)pm)=r)   )rw   r   r   r   r   anyinsertr8   researchgroupendswithrX   r   )r   	dep_groupbase_apt_shellcodedx_apt_update_shellcodeapt_err_msgapt_shellcode_templateapt_shellcoder   r   r   commandsr   r   
r_preambler_cmd_templatebootstrap_cmdpackager   r   subcommands	build_dirsubdirs                         r   generate_shellcodez,DXExecDependencyInstaller.generate_shellcode>  sj   y #^a!_.55=T;M8C 6 E	5 'v.	&0A(u ''-*A'BB+mHX\.]]],}XY]/^^^H A6 :;>RLMAiL$@@LA ;;s3122$}XQT'UUU/DbJ[bbhlbmmJ7N:MH# U'd]ddognoC299'&/JC 5 5zs 5 STU BBB>#8#8*R_#8#`a;;x((8:\]H F 	> BC	""=9#<=""7Y#67""<#c%j/#AB;CJ@FFqI??6*#Mc&k\2F""9v#56C<&&SZ'HI#s*&&s3/?+@'ABfkk+&> > DEF ;;x(('(Q(X(X\d(X(effr   c                 6    t        j                  |d||       y )NT)shellstdoutstderr)
subprocess
check_call)r   r   log_fhs      r   rI   zDXExecDependencyInstaller.run  s    cfVLr   c           
         | j                  dj                  |d   dj                  d |d   D                           | j                  |      }t        j
                  j                  t        j                          dj                  d
i |      }	 t        |d      5 }| j                  ||       d d d        y # 1 sw Y   y xY w# t        j                  $ rn}t        |      5 }t        j                  j                  |j                                d d d        n# 1 sw Y   nxY wt!         d	j                  d
i |      d }~ww xY w)NzInstalling {} packages {}rL   z, c              3   &   K   | ]	  }|d      yw)rc   Nr)   )r   r   s     r   r   z?DXExecDependencyInstaller._install_dep_group.<locals>.<genexpr>  s     =gcc&k=gs   r   zdx_{type}_install_{index}.logr!   )r   z-Error while installing {type} packages {deps}r)   )r   rw   r   r   r+   r   tempfile
gettempdirr9   rI   r   CalledProcessErrorsysr   r<   readr   )r   r   r   log_filenamerG   r   s         r   _install_dep_groupz,DXExecDependencyInstaller._install_dep_group  s!   ,33If4E48II=gU^_eUf=g4gi 	j%%i0ww||H$7$7$9;a;Z;a;a;ndm;no	mlC( )BR() ) ),, 	ml# ,r

  +, , ,'(^(W(^(^(kaj(kll	msN   C B;2C ;C C C EE%.D	ED%	!"EEc                    |d   j                  dd      j                  d      r| j                   dj                  d
i |       	 t	        j
                  |d   |d   t        j                         | j                  dj                  t        j                  |d                      y | j                   d	j                  d
i |       y # t        j                  j                  $ r t	        j
                  |d   |d          Y w xY w)Nrg   z$dnanexus_linkr   zfile-zDownloading bundled file {name}rc   )r   zdx-unpack {}zHSkipping bundled dependency "{name}" because it does not refer to a filer)   )r8   
startswithr   rw   r   download_dxfileWORKSPACE_IDr3   ResourceNotFoundrI   shlexquote)r   bundles     r   _install_dep_bundlez-DXExecDependencyInstaller._install_dep_bundle  s    $<,b1<<WEHH=6==GGHC$$VD\6&>4K\K\] HH^**5;;vf~+FGHHHf_ffpiopq	 ??33 C$$VD\6&>BCs   ,C 9DDc                     | j                   D ]3  }|d   dk(  r| j                  |d   d          #| j                  |       5 y )NrL   r  r   r   )r   r  r  )r   r   s     r   installz!DXExecDependencyInstaller.install  sH     	3I H,((6):1)=>''	2		3r   c                     d|vrt        dj                  |            |j                  d      dk(  rd|vrt        dj                  |            y y )Nrc   z@Expected field "name" to be present in execution dependency "{}"package_managerr   r   z5Execution dependency "{}" does not have a "url" field)r   rw   r8   r   r   s     r   r   z.DXExecDependencyInstaller._validate_dependency  s\    '(j(q(qru(vwwWW&'50U#5E'(_(f(fgj(kll 6F0r   c                 0    d|v ry|j                  dd      S )Nrg   r  r  r   )r8   r  s     r   r   z.DXExecDependencyInstaller._get_dependency_type  s    3;77,e44r   rQ   )r   r   r   r   r   r   r   r   r   rI   r  r  r  r   r   r)   r   r   r   r      sG     >I04d9?gBMm	r3m5r   r   )NN)+r   
__future__r   r   r   r   r+   r  r:   r   r.   rl   rb   r   r   r   collections.abcr   	functoolsr   r
  r   r3   r
   r=   r*   ascii_lettersdigitspunctuation
whitespaceASCII_PRINTABLEr   r   rI   r>   rU   r   r   r   rB   r   objectr   r)   r   r   <module>r     s   " S R T T T T T #    ) 	 &&69K9KKfN_N__:[z		$L(3D$$ 3	, 	z5 z5r   