o
    3gk}                     @  s"  d dl 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mZmZ d dlmZ d dlmZ d dlmZ d dlmZmZmZmZmZ d dlmZmZ d dlZejdddZdddZ dddZ!dddZ"dZ#dZ$dddZ%dddZ&ddd Z'dd#d$Z(dd%d&Z)dd(d)Z*d*d+l+m,Z,m-Z- d,d-dd0d1Z.dd7d8Z/dd9d:Z0dd;d<Z1dd?d@Z2ddBdCZ3d,d,dDddHdIZ4dddNdOZ5dPdQddTdUZ6ddWdXZ7dYd,d,dZddmdnZ8e9 ej:dodPd,dpdqd dsdtZ;ejd*duddvdwZ<dd|d}Z=e;j>d~ddej:dd,ddej:dd3dPddej:dddPddej:ddddPddej?ddd,e=ddddZ@e;j9ddddddZAeAj>ddddddZBeAj>ddddddZCe;j>d=ddej:dd3dPdddddZDe;j9dAdddddZEeEj>dddej?de=ddPddddZFeEj>dddej:ddPddej:ddPddej:dddPddej?de=ddPddddZGe;j>dddej:dddYeHg dddej:ddd,dPddej:dddeIddej:dddeHg dƢddej:dddeIddej:dddeIddej:dddeIddej:dddeIddej:dd,ddej:dddeJddej:dd,dPddej:dd,dPddej:dd,dPddej:dd,dPddej:dd,dPddej?dddPe=ddddZKdddZLeMdkre;dd dS dS (      )annotationsN)IterableSequence)	ExitStack)chain)Path)PIPECompletedProcessPopen
check_callrun)AnyCallablereturnSequence[str] | Nonec                  C  sH   zdd l } W n	 ty   Y nw tjddgS tdrdgS td d S )Nr   -mmypyz|mypy not found, so can't check config with it. See https://github.com/python/mypy#readme if you want to install it and retry)r   ImportErrorsys
executableshutilwhichwarning)r    r   */home/garg/my-data/HPI/my/core/__main__.pymypy_cmd   s   
r   cfg_pathr   CompletedProcess | Nonec                 C  s   i t j}|d}t| |d u rdnd|  }||d< t }|d u r&d S tg |dddddd	d
dtt|d}|S )NMYPYPATH :z--namespace-packagesz--color-outputz--prettyz--show-error-codesz--show-error-contextz--check-untyped-defsz-pz	my.config)stderrstdoutenv)osenvirongetstrr   r   r   )r   r#   mpathcmdmresr   r   r   run_mypy&   s:   

	
r+   xr'   Nonec                 C  s   t j| dd d S )NT)err)clickechor,   r   r   r   eprintA   s   r2   c                 C  s   d dd | jddD S )Nr   c                 s      | ]}d | V  qdS )z   Nr   ).0lr   r   r   	<genexpr>H       zindent.<locals>.<genexpr>Tkeependsjoin
splitlinesr1   r   r   r   indentF   s   r=   u   ✅u   🔲c                 C  s   t td |   d S )N )r2   OKr1   r   r   r   infoO      r@   c                 C     t d|   d S )Nu   ❌ r2   r1   r   r   r   errorS      rD   c                 C  rB   )Nu   ❗ rC   r1   r   r   r   r   W   rE   r   e	Exceptionc                 C  s*   d tt| | j}tjt| d S )Nr   )	r;   	tracebackformat_exceptionrG   __traceback__r   r!   writer=   )rF   tbr   r   r   rL   [   s   rL   c                  C  s   ddl m}  |  }d}| s/|d d d }|jjdd |d	  td
|  d}ntd| d t	 }|r>|sEt
d d S d S )N   get_mycfg_dirFmyconfigz__init__.pyT)parentsa  
### HPI personal config
## see
# https://github.com/karlicoss/HPI/blob/master/doc/SETUP.org#setting-up-modules
# https://github.com/karlicoss/HPI/blob/master/doc/MODULES.org
## for some help on writing your own config

# to quickly check your config, run:
# hpi config check

# to quickly check a specific module setup, run hpi doctor <module>, e.g.:
# hpi doctor my.reddit.rexport

### useful default imports
from my.core import Paths, PathIsh, get_files
###

# most of your configs will look like this:
class example:
    export_path: Paths = '/home/user/data/example_data_dir/'

### you can insert your own configuration below
### but feel free to delete the stuff above if you don't need ti
zcreated empty config: zconfig directory 'z#' already exists, skipping creation)preinitrO   existsparentmkdir
write_textlstripr@   rD   	config_okr   exit)rO   	mycfg_dircreated	my_configcheck_passedr   r   r   config_create`   s"   r_   boolc                  C  s  g } dd l }zt|j}W n ty, } z| | td t| W Y d }~nd }~ww td|  ddlm	} | }dd l
}z%tt|jjd j}t||retd| d  | td W n ty } z| | t| W Y d }~nd }~ww td	|  t K}t|d
 }tjdddt|g}	ztj||dd t|	 tdd|	  W n ty } z| | t| W Y d }~nd }~ww W d    n1 sw   Y  t|}
|
d ur|
j}|dkrtd ntd | td tjt|
jd tjt|
j d zdd l!}W n  ty> } z| | td t| W Y d }~nd }~ww t"| dkrRtdt"|  d dS td dS )Nr   z&failed to determine module import pathzimport order: rM   rN   z%
Seems that the stub config is used (z). This is likely not going to work.
See https://github.com/karlicoss/HPI/blob/master/doc/SETUP.org#setting-up-modules for more information
zbad config pathzconfig path : cfgr   
compileall-qT)dirs_exist_okzsyntax check: r>   zmypy check  : successzmypy check: failedzmypy failedutf8zfailed to import the configzconfig check: z errorsFzconfig check: success!)#rP   list__path__rG   appendrD   rL   r@   rS   rO   my.corer'   r   corerU   
startswithstripRuntimeErrortempfileTemporaryDirectoryr   r   r   copytreer   r;   r+   
returncoder!   rK   r=   decoder"   	my.configlen)errorsrP   pathsrF   rO   r   core_pkg_pathtdtdirr)   mypy_resrcr   r   r   rY      s   






rY   rM   )	HPIModulemodulesFallr   Iterable[HPIModule]c                 c  sb    g }t  D ]}| s|jd ur||j q|V  qt|dkr/tdt| d| d d S d S )Nr   zSkipped z
 modules: z%. Pass --all if you want to see them.)r}   skip_reasonrh   namert   r   )r   skippedmr   r   r   _modules   s   
r   verboselist_allquickfor_modules	list[str]c                   s^  t |dkrd} | rdnd}t  dd l}ddlm} ddlm}m} ddlm	  t |dkr5t
|d	}	n	 fd
d|D }	|	D ]}
|
j}|
j}|d urbtt dtjddd d|dd|  q@zt|}W n5 ty } z)ttjddd d|dd|  t|ttfr|| | rt| W Y d }~q@d }~ww ttjddd d|d ||dd}|d u rtd q@|r| n| }z5i }t|rdt|jv r||d< | |d i |}W d    n1 sw   Y  |d usJ dW n) ty$ } ztdtjddd d|  | rt| W Y d }~q@d }~ww td|  q@d S )!Nr   Tr   z*; pass --verbose to print more informationrM   )warn_my_config_import_error)	get_statsquick_statsr|   r~   c                   s   g | ]} |d dqS )N)r   r   r   r4   r   r   r   r   
<listcomp>      z!modules_check.<locals>.<listcomp>r>   SKIPyellowfgz: z<50FAILredz loading failedr?   greenz  : )guessz2       - no 'stats' function, can't check the datar   zstats() returned Nonez     - zstats:z&                      computing failedz    - stats: r   )rt   tabulate_warnings
contextlibrD   r   statsr   r   utilr|   r   r   r   r2   OFFr/   style	importlibimport_modulerG   
isinstancer   AttributeErrorrL   r@   nullcontextcallableinspect	signature
parametersr   )r   r   r   r   vwr   r   r   r   modsmrskipr   modrF   r   quick_contextkwargsreseer   r   r   modules_check   sd   *$r   c                 C  sr   t   t| dD ].}|j}|j}|d u rt}d}nt}dtjd| ddd }t| d|d|  qd S )	Nr~   r   r>   z[disabled: ]r   r   50)	r   r   r   r   r?   r   r/   r   r0   )r   r   r   srpresufr   r   r   list_modulesA  s   r   c                    s&   ddl } | j d fdd}|| _dS )z<
    Helper to avoid visual noise in hpi modules/doctor
    r   Nr   r'   c                    s*    | i |}d dd |jddD S )Nr   c                 s  r3   )z  Nr   r4   r,   r   r   r   r6   \  r7   z6tabulate_warnings.<locals>.override.<locals>.<genexpr>Tr8   r:   )argsr   r   origr   r   overrideZ  s   z#tabulate_warnings.<locals>.override)r   r'   )warningsformatwarning)r   r   r   r   r   r   R  s   
r   r}   Sequence[str]c                   s   ddl m   fdd| D }g }|D ]+}|jd urt|j |j}|d u r0td|j d q|D ]}||vr=|| q2q|S )NrM   module_by_namec                   s   g | ]} |qS r   r   )r4   moduler   r   r   r   e  s    z_requires.<locals>.<listcomp>zModule z has no REQUIRES specification)discovery_purer   legacyr   requiresr   rh   )r}   r   r   r   reqsrr   r   r   	_requiresb  s    


r   r   c                 C  sJ   t | tr| g} dd t| dD }td|   |D ]}t| qd S )Nc                 S  s   g | ]}d | d qS )'r   r   r   r   r   r   y  r   z#module_requires.<locals>.<listcomp>r}   zdependencies of )r   r'   r   r2   r/   r0   )r   rsr,   r   r   r   module_requiresu  s   
r   )parallelbreak_system_packagesuserr   r   c              	   C  sR  t |tr|g}t|}t|dkrtd d S dtjv }tjdg|r&dgng dd| r1dgng |r8d	gng }g }|rStj	d
vrS|D ]}|
g || qFn|rYtd |
|t|  t :}	g }
|D ]}tddttj|  |	t|}|

| qj|
D ]}| }|dksJ |qW d    d S 1 sw   Y  d S )Nr   z7requirements list is empty, no need to install anythingHPI_MODULE_INSTALL_USE_UVr   uvpipinstall--user--break-system-packages)win32cygwindarwinzNparallel install is not supported on this platform, installing sequentially...z	Running: r>   )r   r'   r   rt   r   r$   r%   r   r   platformrh   rf   r   r2   r;   mapshlexquoteenter_contextr
   wait)r   r   r   r   requirementsuse_uvpre_cmdcmdsr   
exit_stackpopensr)   popenretr   r   r   module_install  sL   

"r   Select from: choicespromptintc                 C  s   t | dks
J dt|d  tdd }i }t| dD ]"\}}|dk r)t|nt|| }|d ||< td| d|  qtd	 	 t }||vr[t| dt|	   qD|| S )zh
    Basic menu allowing the user to select one of the choices
    returns the index the user chose
    r   z$Didnt receive any choices to prompt!
a
   rM   	z. r   Tz not in )
rt   r2   ord	enumerater'   chrr/   getcharrf   keys)r   r   
chr_offset
result_mapioptcharchr   r   r   _ui_getchar_pick  s   r   T)r   qualified_namesIterable[Callable[..., Any]]c                #  sv   ddl m}m} ddlm  tj sd}| D ]}z||V  W q |y } zzt	|}W n t
yG } ztd| d ||d }~ww  fddt|tjD }t|d	krftd
| d |t|dkrr|d	 V  n<dd |D }	|du rtd td |	D ]}
td| d|
  q|t|	d| d}td|	|  d || V  W Y d }~qd }~ww d S )NrM   )QueryExceptionlocate_qualified_functionis_data_providerFzDuring fallback, importing 'z' as module failedc                   s   g | ]
\}} |r|qS r   r   )r4   _fr  r   r   r     s    z/_locate_functions_or_prompt.<locals>.<listcomp>r   z7During fallback, could not find any data providers in 'r   c                 S     g | ]}|j qS r   )__name__r4   r  r   r   r   r         z]During fallback, more than one possible data provider, can't prompt since STDOUT is not a TTYzSpecify one of:r   .z$Which function should be used from 'z'?z
Selected ')queryr   r   r   r  r   r"   isattyr   r   rG   r2   r   
getmembers
isfunctionrt   r   )r   r   r   r   qualnameqr_errr   iedata_providersr   funcnamechosen_indexr   r  r   _locate_functions_or_prompt  sF   

r  excc                 C  s,   ddl m} |ddd}|d|   d S )Nr   )make_loggerCLIr   )levelzhpi query: )ri   r  	exception)r  r  loggerr   r   r   _warn_exceptions  s   r  json)outputstreamreverser  r  	order_key
str | Noneorder_by_value_typetype | Noneafterr   beforewithinr  limit
int | Nonedrop_unsortedwrap_unsortedwarn_exceptionsraise_exceptionsdrop_exceptionsc                 C  s  ddl m}m} tdd t|D  }||||||||d||	|
||t||d}| dkrYddlm} |rN|D ]}tj	
|| tj	
d	 q6tj	  d S t|t| d S | d
krxddlm} |rp|D ]}|| qgd S |t| d S | dkrddlm} |s|sd}||tj	D ]}|rt| q|r||r	 qtj	  d S t|}tdtjddd d zdd l}W n ty   td dd l}|jt d Y d S w |  d S )NrM   )
RangeTupleselect_rangec                 s  s    | ]}| V  qd S )Nr   r  r   r   r   r6     s    z&query_hpi_functions.<locals>.<genexpr>)r$  r%  r&  )r   r"  unparsed_ranger  r'  r)  r*  r+  	warn_funcr,  r-  r  )dumpsr   pprintr   )r3  gpx)locations_to_gpxTz(
Interact with the results by using the r   r   r   z
 variable
zj'repl' typically uses ipython, install it with 'python3 -m pip install ipython'. falling back to stdlib...)local)query_ranger.  r/  r   r  r  	serializer2  r   r"   rK   flushr/   r0   rf   r3  my.location.commonr5  r2   r   IPythonModuleNotFoundErrorcodeinteractlocalsembed)r  r  r   r   r"  r$  r%  r&  r  r'  r)  r*  r+  r,  r-  r.  r/  	input_srcr   r2  itemr3  r5  r  r;  r=  r   r   r   query_hpi_functions  sl   

rC  z--debugzShow debug logs)is_flagdefaulthelpdebugc                 C  s8   | rdt jd< tt d }|jdd t | dS )z
    Human Programming Interface

    Tool for HPI
    Work in progress, will be used for config management, troubleshooting & introspection
    rG  LOGGING_LEVEL_HPIhpi_temp_dirT)exist_okN)r$   r%   r   rn   
gettempdirrV   chdir)rG  ry   r   r   r   mainc  s
   

rM  )maxsizec                   C  s   t dd t D S )zEShould include all modules, in case user is trying to diagnose issuesc                 S  r  r   )r   r   r   r   r   r     r  z"_all_mod_names.<locals>.<listcomp>)sortedr}   r   r   r   r   _all_mod_names  s   rP  ctxclick.Contextr   
incompletec                   s    fddt  D S )Nc                   s   g | ]	}|  r|qS r   )rk   r   rS  r   r   r     s    z(_module_autocomplete.<locals>.<listcomp>)rP  )rQ  r   rS  r   rT  r   _module_autocomplete  rA   rU  doctorzrun various checks)r   
short_helpz--verbose/--quietz!Print more diagnostic information)rE  rF  z--allz$List all modules, including disabled)rD  rF  rc   z--quickz)Only run partial checks (first 100 items)z-Sz--skip-config-check	skip_confzSkip configuration checkMODULE)nargsrequiredshell_completec                 C  s"   |st   t| ||t|d dS )z
    Run various checks

    MODULE is one or more specific module names to check (e.g. my.reddit.rexport)
    Otherwise, checks all modules
    )r   r   r   r   N)rY   r   rf   )r   r   r   rX  r   r   r   r   
doctor_cmd  s   r^  rQ   zwork with configurationc                   C     dS )zAct on your HPI configurationNr   r   r   r   r   
config_grp     r`  checkzcheck configc                  C  s"   t  } t| rd dS d dS )z!Check your HPI configuration filer   FN)rY   r   rZ   )okr   r   r   config_check_cmd  s   rd  createzcreate user configc                   C  s
   t   dS )z&Create user configuration file for HPIN)r_   r   r   r   r   config_create_cmd  s   
rf  zlist available modulesc                 C     t | d dS )zList available modulesr   N)r   rh  r   r   r   
module_cmd  s   ri  zmodule managementc                   C  r_  )zModule managementNr   r   r   r   r   
module_grp  ra  rj  r   zprint module reqsMODULES)r]  r[  r\  c                 C  rg  )zo
    Print MODULES requirements

    MODULES is one or more specific module names (e.g. my.reddit.rexport)
    )r   N)r   r   r   r   r   module_requires_cmd  s   rl  r   zinstall module depsr   zsame as pip --userz
--parallelz/EXPERIMENTAL. Install dependencies in parallel.z-Br   zVBypass PEP 668 and install dependencies into the system-wide python package directory.c                 C  s   t | |||d dS )z
    Install dependencies for modules using pip

    MODULES is one or more specific module names (e.g. my.reddit.rexport)
    )r   r   r   r   N)r   )r   r   r   r}   r   r   r   module_install_cmd  s   rm  r
  z#query the results of a HPI functionz-oz--output)r  r3  replr4  z*what to do with the result [default: json])rE  typerF  z-sz--streamzIstream objects from the data source instead of printing a list at the end)rE  rD  rF  z-kz--order-keyz_order by an object attribute or dict key on the individual objects returned by the HPI functionz-tz--order-type)datetimedater   floatz0order by searching for some type on the iterablez-az--afterzMwhile ordering, filter items for the key or type larger than or equal to thisz-bz--beforezBwhile ordering, filter items for the key or type smaller than thisz-wz--withinzQa range 'after' or 'before' to filter items by. see above for further explanationz-rz--recentzYa shorthand for '--order-type datetime --reverse --before now --within'. e.g. --recent 5dz--reverse/--no-reversez/reverse the results returned from the functionsz-lz--limitz7limit the number of items returned from the (functions)z--drop-unsortedz]if the order of an item can't be determined while ordering, drop those items from the resultsz--wrap-unsortedzaif the order of an item can't be determined while ordering, wrap them into an 'Unsortable' objectz--warn-exceptionsz:if any errors are returned, print them as errors on STDERRz--raise-exceptionszRif any errors are returned (as objects, not raised) from the functions, raise themz--drop-exceptionsz8ignore any errors returned as objects from the functionsFUNCTION_NAMEfunction_name
order_typerecentc                 C  s   ddl m}m } |dkr|}n|dkr|}n|dkrt}n	|dkr$t}nd}|dur5d}|p/|}|}|	 }	d	d
lm} zt||t| ||||||	|
|||||d W dS  |yq } ztt	| t
d	 W Y d}~dS d}~ww )a|  
    This allows you to query the results from one or more functions in HPI

    By default this runs with '-o json', converting the results
    to JSON and printing them to STDOUT

    You can specify '-o pprint' to just print the objects using their
    repr, or '-o repl' to drop into a ipython shell with access to the results

    While filtering using --order-key datetime, the --after, --before and --within
    flags parse the input to their datetime and timedelta equivalents. datetimes can
    be epoch time, the string 'now', or an date formatted in the ISO format. timedelta
    (durations) are parsed from a similar format to the GNU 'sleep' command, e.g.
    1w2d8h5m20s -> 1 week, 2 days, 8 hours, 5 minutes, 20 seconds

    As an example, to query reddit comments I've made in the last month

    
    hpi query --order-type datetime --before now --within 4w my.reddit.all.comments
    or...
    hpi query --recent 4w my.reddit.all.comments

    
    Can also query within a range. To filter comments between 2016 and 2018:
    hpi query --order-type datetime --after '2016-01-01' --before '2019-01-01' my.reddit.all.comments
    r   )rq  rp  rp  rq  r   rr  NnowrM   )r   )r  r  r   r   r"  r$  r%  r&  r  r'  r)  r*  r+  r,  r-  )rp  rq  r   rr  r
  r   rC  rf   r2   r'   r   rZ   )rt  r  r  r   ru  r$  r%  r&  rv  r  r'  r)  r*  r+  r,  r-  rq  rp  chosen_order_typer   qer   r   r   	query_cmd  sN   trz  c                  C  sL   ddl m}  |  tg d}|jdksJ d|jv sJ d|jv s$J d S )Nr   )	CliRunner)r   r   zmy.github.ghexportzmy.browser.exportzgithub.com/karlicoss/ghexportbrowserexport)click.testingr{  invokerM  	exit_coder  )r{  resultr   r   r   test_requires  s
   r  __main__hpi)	prog_name)r   r   )r   r   r   r   )r,   r'   r   r-   )r,   r'   r   r'   )rF   rG   r   r-   )r   r-   )r   r`   )r   r`   r   r   )
r   r`   r   r`   r   r`   r   r   r   r-   )r   r`   r   r-   )r}   r   r   r   )r   r   r   r-   )
r   r`   r   r   r   r`   r   r`   r   r-   )r   )r   r   r   r'   r   r   )r   r   r   r`   r   r   )r  rG   r   r-   ) r  r'   r  r`   r   r   r   r!  r"  r#  r$  r   r%  r   r&  r   r  r`   r'  r(  r)  r`   r*  r`   r+  r`   r,  r`   r-  r`   r   r-   )rG  r`   r   r-   )r   r   )rQ  rR  r   r   rS  r'   r   r   )r   r`   r   r`   r   r`   rX  r`   r   r   r   r-   )r}   r   r   r-   )
r   r`   r   r`   r   r`   r}   r   r   r-   )"rt  r   r  r'   r  r`   r   r!  ru  r!  r$  r!  r%  r!  r&  r!  rv  r!  r  r`   r'  r(  r)  r`   r*  r`   r+  r`   r,  r`   r-  r`   r   r-   )N
__future__r   	functoolsr   r   r$   r   r   r   rn   rH   collections.abcr   r   r   r   	itertoolsr   pathlibr   
subprocessr   r	   r
   r   r   typingr   r   r/   	lru_cacher   r+   r2   r=   r?   r   r@   rD   r   rL   r_   rY   r   r|   r}   r   r   r   r   r   r   r   r   r  r  rC  groupoptionrM  rP  rU  commandargumentr^  r`  rd  rf  ri  rj  rl  rm  Choicer'   r   rz  r  r  r   r   r   r   <module>   sX   








0^

E



2
0]
	
.
b
	