o
    ǯh+                     @   s  d dl Z d dlmZ d dlmZmZ d dlmZ d dlm	Z	 d dl
mZmZ d dlmZmZmZ d dlmZ zd d	lmZ ejZW n eyP   d d
lmZ Y nw d dlmZ dd Zdd Zdd Zdd Zdd Zdd Zdd Z dd Z!dd Z"dd Z#d d! Z$d"d# Z%d$d% Z&d&d' Z'd(d) Z(G d*d+ d+eZ)G d,d- d-eZ*d.d/ Z+d0d1 Z,d2d3 Z-d4d5 Z.e fd6d7Z/e d8fd9d:Z0ed;d<d=d> Z1d?d@ Z2dAdB Z3dCdD Z4d8dEdFdGdHZ5dIdJ Z6dS )K    N)ContextDecorator)	lru_cachewraps)
ModuleType)settings)ImproperlyConfiguredValidationError)DEFAULT_DB_ALIAS
connectionconnections)import_stringapps)	get_model)mailc                   C   
   t tjS N)r   r   TENANT_MODEL r   r   Q/var/www/Befach/backend/venv/lib/python3.10/site-packages/django_tenants/utils.pyget_tenant_model      
r   c                   C   r   r   )r   r   TENANT_DOMAIN_MODELr   r   r   r   get_tenant_domain_model   r   r   c                   C   s   t tdtS )NTENANT_DB_ALIAS)getattrr   r	   r   r   r   r   get_tenant_database_alias      r   c                   C      t tddS )NPUBLIC_SCHEMA_NAMEpublicr   r   r   r   r   r   get_public_schema_name    r   r"   c                   C   s   t tdi S )NTENANT_TYPESr!   r   r   r   r   get_tenant_types$   r   r$   c                  C   s   t tdd} t| S )NTENANT_BASE_MIGRATE_COMMANDz/django.core.management.commands.migrate.Command)r   r   r   )
class_pathr   r   r   %get_tenant_base_migrate_command_class(   s   r'   c                   C   r   )NHAS_MULTI_TYPE_TENANTSFr!   r   r   r   r   has_multi_type_tenants1   r   r)   c                   C   r   )NMULTI_TYPE_DATABASE_FIELD r!   r   r   r   r   "get_multi_type_database_field_name5   r   r,   c                   C   s"   t  rt t  d S ttddS )NURLCONFPUBLIC_SCHEMA_URLCONFurls_public)r)   r$   r"   r   r   r   r   r   r   get_public_schema_urlconf9   s   r0   c                  C   s&   t  sJ dt } dd |  D S )z6This is to allow a choice field for the type of tenantFzBget_tenant_type_choices should only be used for multi type tenantsc                 S   s   g | ]}||fqS r   r   ).0kr   r   r   
<listcomp>G       z+get_tenant_type_choices.<locals>.<listcomp>)r)   r$   keys)tenant_typesr   r   r   get_tenant_type_choices@   s   r7   c                   C   r   )NTENANT_LIMIT_SET_CALLSFr!   r   r   r   r   get_limit_set_callsJ   r   r9   c                  C   s   t tddpd} | dS )NTENANT_SUBFOLDER_PREFIXr+   z/ )r   r   strip)subfolder_prefixr   r   r   get_subfolder_prefixN   s   
r=   c                  C   (   t tdd} | rt tddstd| S )
    If TENANT_CREATION_FAKES_MIGRATIONS, tenants will be created by cloning an
    existing schema specified by TENANT_CLONE_BASE.
     TENANT_CREATION_FAKES_MIGRATIONSFTENANT_BASE_SCHEMAzdYou must specify a schema name in TENANT_BASE_SCHEMA if TENANT_CREATION_FAKES_MIGRATIONS is enabled.r   r   r   )fakedr   r   r   get_creation_fakes_migrationsS      rD   c                  C   r>   )r?   rA   Fr@   z\TENANT_CREATION_FAKES_MIGRATIONS setting must be True to use TENANT_BASE_SCHEMA for cloning.rB   )schemar   r   r   get_tenant_base_schemab   rE   rG   c                   C   s   t tdd S )NTENANT_MIGRATION_ORDERr!   r   r   r   r   get_tenant_migration_orderq   r   rI   c                       ,   e Zd Z fddZdd Zdd Z  ZS )schema_contextc                    (   |d | _ |dt | _t   d S Nr   database)schema_namegetr   rN   super__init__selfargskwargs	__class__r   r   rR   w      
zschema_context.__init__c                 C   s&   t | j | _tj| _| j| j d S r   )r   rN   r
   tenantprevious_tenant
set_schemarO   rT   r   r   r   	__enter__|      zschema_context.__enter__c                 G   *   | j d u r| j  d S | j| j  d S r   r[   r
   set_schema_to_public
set_tenantrT   excr   r   r   __exit__      
zschema_context.__exit____name__
__module____qualname__rR   r^   rf   __classcell__r   r   rW   r   rK   u       rK   c                       rJ   )tenant_contextc                    rL   rM   )rZ   rP   r   rN   rQ   rR   rS   rW   r   r   rR      rY   ztenant_context.__init__c                 C   s&   t | j | _tj| _| j| j d S r   )r   rN   r
   rZ   r[   rc   r]   r   r   r   r^      r_   ztenant_context.__enter__c                 G   r`   r   ra   rd   r   r   r   rf      rg   ztenant_context.__exit__rh   r   r   rW   r   rn      rm   rn   c                 C   s2   t tdrtjr| tjr| ttjd } | S )z;
    Removes the TENANT_TOKEN from a particular string
    r.   N)hasattrr   r.   
startswithlen)
url_stringr   r   r   clean_tenant_url   s   

rs   c                 C   s   t | S )zL
    Legacy function - just in case someone is still using the old name
    )
remove_wwwhostnamer   r   r   remove_www_and_dev   s   rw   c                 C   s   |  dr| dd S | S )z
    Removes www. from the beginning of the address. Only for
    routing purposes. www.test.com/login/ and test.com/login/ should
    find the same tenant.
    zwww.   N)rp   ru   r   r   r   rt      s   
rt   c                   C   s
   t tdS )z
    I know this is very ugly! I'm looking for more elegant solutions.
    See: http://stackoverflow.com/questions/6957016/detect-django-testing-mode
    outbox)ro   r   r   r   r   r   django_is_in_test_mode   s   
rz   c                 C   sH   t | }| }d}||| f | }|r|d }nd}|  |S )NzUSELECT EXISTS(SELECT 1 FROM pg_catalog.pg_namespace WHERE LOWER(nspname) = LOWER(%s))r   F)r   cursorexecutefetchoneclose)rO   rN   _connectionr{   sqlrowexistsr   r   r   schema_exists   s   
r   Tc                 C   s   ddl m} t| }| }t|rtd||stddtj	| j
tj	|}|| |  || _
|rA|   dS dS )zR
    This renames a schema to a new name. It checks to see if it exists first
    r   )is_valid_schema_namezNew schema name already existsz(Invalid string used for the schema name.zALTER SCHEMA {0} RENAME TO {1}N)&django_tenants.postgresql_backend.baser   r   r{   r   r   formatr
   ops
quote_namerO   r|   r~   save)rZ   new_schema_namerN   r   r   r   r{   r   r   r   r   schema_rename   s    

r      )maxsizec                    s   ddl m} | dd }zt| }W n ty   | Y S w t|tr&| n|j  fdd| D }t	|dkr<|S |d S )Nr   r   .c                    s   g | ]
}|j  kr|jqS r   )namelabel)r1   
app_configapp_namer   r   r3      s
    
z!get_app_label.<locals>.<listcomp>   )
django.appsr   splitr   ImportError
isinstancer   r   get_app_configsrq   )appr   	candidateimported_app	app_labelr   r   r   get_app_label   s   
r   c                 C   s   dd | D S )z=
    Returns a list of app labels of the given apps_list
    c                 S   s   g | ]}t |qS r   )r   )r1   r   r   r   r   r3     r4   zapp_labels.<locals>.<listcomp>r   )	apps_listr   r   r   
app_labels  s   r   c              	   C   s4   z| t j W S  ttfy   tj| t j Y S w )a  
    Convenience function for parsing django-tenants' path configuration strings.

    If the string contains '%s', then the current tenant's schema name will be inserted at that location. Otherwise
    the schema name will be appended to the end of the string.

    :param config_path: A configuration path string that optionally contains '%s' to indicate where the tenant
    schema name should be inserted.

    :return: The formatted string containing the schema name
    )r
   rO   	TypeError
ValueErrorospathjoin)config_pathr   r   r   parse_tenant_config_path	  s
   r   c                  C   s   t tdd} t tdg }| s_|rat |v rtdt  t }t .}|d|jj	g |
 rJt||j jddd}|rJtd	t| W d    n1 sTw   Y  t  d S d S d S )
NSKIP_PG_EXTRA_VALIDATIONFPG_EXTRA_SEARCH_PATHSz0%s can not be included on PG_EXTRA_SEARCH_PATHS.z>SELECT 1 FROM information_schema.tables WHERE table_name = %s;rO   T)flatz<Do not include tenant schemas (%s) on PG_EXTRA_SEARCH_PATHS.)r   r   r"   r   r   r
   r{   r|   _metadb_tabler}   setintersectionobjectsallvalues_listlistr~   )skip_validationextra_extensionsmodelr{   invalid_schemasr   r   r   validate_extra_extensions  s:   

r   F)tenant_schemapublic_schemac                    s6    fdd}t |dkrt|d r||d S |S )a%  
    Decorator to control which schemas a data migration will execute on.
    
    :param tenant_schema: If True (default), the data migration will execute on the tenant schema(s).
    :param public_schema: If True, the data migration will execute on the public schema.

    :return: None
    c                    s   t   fdd}|S )Nc               
      sr   z| \}}W n t y } zt d| d }~ww r#|jjt ks,r5|jjt kr7 | i | d S d S d S )NzADecorator requires apps & schema_editor as positional arguments: )	Exceptionr
   rO   r"   )_argsrV   _schema_editorexcp)funcr   r   r   r   wrapperG  s   z<tenant_migration.<locals>._tenant_migration.<locals>.wrapper)r   )r   r   r   r   )r   r   _tenant_migrationF  s   
z+tenant_migration.<locals>._tenant_migrationr   r   )rq   callable)r   r   rU   r   r   r   r   tenant_migration<  s   
r   c                 C   s   t | dr| jS dS )z,This gets the tenant object from the requestrZ   N)ro   rZ   )requestr   r   r   
get_tenantZ  s   
r   )7r   
contextlibr   	functoolsr   r   typesr   django.confr   django.core.exceptionsr   r   	django.dbr	   r
   r   django.utils.module_loadingr   r   r   r   r   django.db.models.loadingdjango.corer   r   r   r   r"   r$   r'   r)   r,   r0   r7   r9   r=   rD   rG   rI   rK   rn   rs   rw   rt   rz   r   r   r   r   r   r   r   r   r   r   r   r   <module>   sZ    
	

