B
    `G~                 @   sZ  d dl Z d dlZd dlmZ d dlmZ d dl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 d d
lmZ d dlmZmZ d dlmZ e je j e j ZG dd deZ G dd deZ!G dd deZ"G dd deZ#G dd dZ$G dd deZ%G dd deZ&G dd deZ'G dd dZ(G dd  d eZ)dS )!    N)datetime)Enum)urandom)randint)load_and_validate_keys)UnexpectedResponseError)BaseDerivedBaseImagePropertyRegion)MappedObject)FilterableAttribute)	IPAddressIPv6Pool)PaginatedListc               @   sv   e Zd ZdZdZdZeddedde eddedde edde edde e e eedd	Zd
d Z	dS )Backupz*/linode/instances/{linode_id}/backups/{id}backups	linode_idT)
identifier)is_datetime)volatile)slug_relationship)idcreateddurationupdatedfinishedmessagestatustyper   labelconfigsdisksregionc             K   sD   dt t|tr|jn|i}|| | jjdtj	| |d dS )Nr   z
{}/restore)modeldataT)

issubclassr    r   r   update_clientpostformatr   api_endpoint)selfZlinodekwargsd r0   I/home/dcms/DCMS/lib/python3.7/site-packages/linode_api4/objects/linode.py
restore_to(   s
    
zBackup.restore_toN)
__name__
__module____qualname__r,   derived_url_pathparent_id_namer   r   
propertiesr2   r0   r0   r0   r1   r      s"   r   c            
   @   sx   e Zd ZdZdZdZeddeddedddeddeddd	e eddeddd
Zdd ZdddZ	dd Z
dS )Diskz(/linode/instances/{linode_id}/disks/{id}r#   r   T)r   )r   )mutable
filterable)r;   )r;   r   )r   r   r!   sizer   
filesystemr   r   c             C   sB   | j jtj| i d}d|kr(td|dt| j |d | j|}|S )N)r%   r&   r   z%Unexpected response duplicating disk!)json)r)   r*   r9   r,   r   r   )r-   resultr/   r0   r0   r1   	duplicateD   s
    zDisk.duplicateNc             C   sZ   |}|st  }d|i}| jjtj| |d}d|kr@td|d| | |sVd|fS dS )Npassword)r%   r&   r   z%Unexpected response duplicating disk!)r>   T)Instancegenerate_root_passwordr)   r*   r9   r,   r   	_populate)r-   Zroot_passwordZrpassparamsr?   r0   r0   r1   reset_root_passwordN   s    
zDisk.reset_root_passwordc             C   s"   | j jdtj| d|id dS )a>  
        Resizes this disk.  The Linode Instance this disk belongs to must have
        sufficient space available to accommodate the new size, and must be
        offline.

        **NOTE** If resizing a disk down, the filesystem on the disk must still
        fit on the new disk size.  You may need to resize the filesystem on the
        disk first before performing this action.

        :param new_size: The intended new size of the disk, in MB
        :type new_size: int

        :returns: True if the resize was initiated successfully.
        :rtype: bool
        z	{}/resizer<   )r%   r&   T)r)   r*   r+   r9   r,   )r-   Znew_sizer0   r0   r1   resizea   s    zDisk.resize)N)r3   r4   r5   r,   r6   r7   r   r8   r@   rF   rG   r0   r0   r0   r1   r9   3   s   



r9   c               @   s^   e Zd ZdZeddedde eddeddedde eddeddeddd
ZdS )Kernelz/linode/kernels/{id}T)r   )r;   )r   )
r   
deprecateddescriptionr   kvmr!   ZupdatesversionarchitectureZxenN)r3   r4   r5   r,   r   r8   r0   r0   r0   r1   rH   v   s   rH   c                   sv   e Zd ZdZeddeddeddedde e eddeddeddeddd
Z fddZedZ  Z	S )	Typez/linode/types/{id}T)r;   )r   )
Zdiskr   r!   Znetwork_outZpriceZaddonsZmemorytransferZvcpusZgpusc                s6   t  | d|kr&t| d|d  nt| dd dS )zT
        Allows changing the name "class" in JSON to "type_class" in python
        class
type_classN)superrD   setattr)r-   r>   )	__class__r0   r1   rD      s    zType._populaterP   )
r3   r4   r5   r,   r   r8   rD   r   rQ   __classcell__r0   r0   )rT   r1   rN      s   rN   c               @   s*   e Zd ZdZd
ddZdd Zdd Zd	S )ConfigInterfacez]
    This is a helper class used to populate 'interfaces' in the Config calss
    below.
     c             C   s   || _ || _|| _dS )z/
        Creates a new ConfigInterface
        N)r!   ipam_addresspurpose)r-   rY   r!   rX   r0   r0   r1   __init__   s    zConfigInterface.__init__c             C   s"   | j dkrdS d| j| j | jS )NpubliczPublic Interfacez+Interface {}; purpose: {}; ipam_address: {})rY   r+   r!   rX   )r-   r0   r0   r1   __repr__   s    
zConfigInterface.__repr__c             C   s   | j | j| jdS )z/
        Returns this object as a dict
        )r!   rX   rY   )r!   rX   rY   )r-   r0   r0   r1   
_serialize   s    zConfigInterface._serializeN)rW   rW   )r3   r4   r5   __doc__rZ   r\   r]   r0   r0   r0   r1   rV      s   
rV   c               @   s   e Zd ZdZdZdZeddedde eddeddeedddedd	eed
e edddedddedddedddedddedddZ	dd Z
dd ZdS )Configz*/linode/instances/{linode_id}/configs/{id}r"   r   T)r   )r   )r:   )relationshipr:   r;   )r;   )r`   )r:   r;   )r   r   Zhelpersr   Zroot_devicekerneldevicesZinitrdr   commentsr!   Z	run_levelZ	virt_modeZmemory_limit
interfacesc             C   s   ddl m} t| | i }xt|d  D ]d\}}|s@d||< q*d}d|krn|d rntj|d | j| jd}n|j|d | j| jd}|||< q*W | 	dt
f | g }d|krd	d
 |d D }| 	d| dS )z;
        Map devices more nicely while populating.
           )Volumerb   Ndisk_id)Z	parent_id	volume_idrd   c             S   s&   g | ]}t |d  |d |d dqS )rY   r!   rX   )r!   rX   )rV   ).0cr0   r0   r1   
<listcomp>   s   z$Config._populate.<locals>.<listcomp>)volumerf   r	   rD   itemsr9   Zmake_instancer)   r   _setr   )r-   r>   rf   rb   Zdevice_indexZdevicedevrd   r0   r0   r1   rD      s(    
zConfig._populatec             C   sN   t | }g }x2| jD ](}t|tr4||  q|| qW ||d< |S )zH
        Overrides _serialize to transform interfaces into json
        rd   )r	   r]   rd   
isinstancerV   append)r-   partialrd   rj   r0   r0   r1   r]     s    

zConfig._serializeN)r3   r4   r5   r,   r6   r7   r   rH   r9   r8   rD   r]   r0   r0   r0   r1   r_      s(   




#r_   c               @   s  e Zd ZdZedddedddedddeddeddedddeeddedd	eeddeed
eed
ee	de e e e e edd	dZ
edd Zedd Zedd Zdd Zdd Zd?ddZdd Zdd Zdd Zed d! Zddg g g fd"d#Zd@d%d&Zd'd( Zd)d* ZdAd+d,ZdBd-d.ZdCd/d0Zd1d2 Zd3d4 Zd5d6 Z d7d8 Z!dddg g dddfd9d:Z"ed;d< Z#d=d> Z$dS )DrB   z/linode/instances/{id}T)r   r;   )r:   r;   )r   )r   )r   r   )r   r;   )r:   )Zderived_class)r   )r   r!   groupr   r   r   r$   Zalertsimager#   r"   r    r   ipv4ipv6
hypervisorspecstagsc             C   s  t | ds|| jjdtj| d}d|kr8td|dg }x0|d d D ] }t| j|d |}|| qJW g }x0|d d	 D ] }t| j|d |}|| qW g }x0|d d
 D ] }t| j|d |}|| qW t| j|d d d |d d }t| j|d d d |d d }g }	x,|d d D ]}
|	t	| j|
d  q0W t
f |||d|||	dd}| d| | jS )z
        The ips related collection is not normalized like the others, so we have to
        make an ad-hoc object to return for its response
        _ipsz{}/ips)r%   ru   zUnexpected response loading IPs)r>   r[   addressprivatesharedrv   slaac
link_localglobalrange)r[   r|   r}   )r~   r   pools)ru   rv   )hasattrr)   getr+   rB   r,   r   r   rq   r   r   rn   rz   )r-   r?   Zv4pubrj   iZv4priZ
shared_ipsr~   r   r   pipsr0   r0   r1   r   .  s@    zInstance.ipsc          	   C   s   t | ds| jjdtj| d}d|kr6td|dg }x0|d D ]$}t| j|d | j|}|	| qDW d}|d	 d
 rt| j|d	 d
 d | j|d	 d
 }d}|d	 d rt| j|d	 d d | j|d	 d }| 
dtf |||dd | jS )zZ
        The backups response contains what backups are available to be restored.
        _avail_backupsz
{}/backups)r%   	automaticz.Unexpected response loading available backups!)r>   r   Nsnapshotcurrentin_progress)r   r   )r   r   )r   r)   r   r+   rB   r,   r   r   r   rq   rn   r   r   )r-   r?   r   acurZsnapZpsnapr0   r0   r1   available_backupsc  s*    

zInstance.available_backupsc             C   sN   t | dsH| jjdtj| d}d|kr2tdtf |}t| d| | j	S )z)
        Get per-linode transfer
        	_transferz{}/transfer)r%   usedz/Unexpected response when getting Transfer Pool!)
r   r)   r   r+   rB   r,   r   r   rS   r   )r-   r?   Zmappedr0   r0   r1   rO     s    

zInstance.transferc             C   st   |d k	rdd|kr0d|d kr0|d d |d d< d|krdt |d trdx|d D ]}|d |d< qPW t| | d S )Nru   r{   r   rv   r   )rp   listr   rD   )r-   r>   jr0   r0   r1   rD     s    zInstance._populatec             C   s8   t | dr| `t | dr| `t | dr*| `t|  dS )z Clear out cached properties r   rz   r   N)r   r   rz   r   r   
invalidate)r-   r0   r0   r1   r     s    


zInstance.invalidateNc             C   s8   | j jdtj| |r d|jind d}d|kr4dS dS )Nz{}/bootZ	config_id)r%   r&   errorFT)r)   r*   r+   rB   r,   r   )r-   configrespr0   r0   r1   boot  s    (zInstance.bootc             C   s(   | j jdtj| d}d|kr$dS dS )Nz{}/shutdown)r%   r   FT)r)   r*   r+   rB   r,   )r-   r   r0   r0   r1   shutdown  s    zInstance.shutdownc             C   s(   | j jdtj| d}d|kr$dS dS )Nz	{}/reboot)r%   r   FT)r)   r*   r+   rB   r,   )r-   r   r0   r0   r1   reboot  s    zInstance.rebootc             K   sT   t t|tr|jn|}d|i}|| | jjdtj	| |d}d|krPdS dS )Nr    z	{}/resize)r%   r&   r   FT)
r'   r    r   r   r(   r)   r*   r+   rB   r,   )r-   new_typer.   rE   r   r0   r0   r1   rG     s    
zInstance.resizec                 sF   dd  d  fddttddD } t| dkrB| d d } | S )Nc             S   s"   t jd dk rt| dd} | S )Nr      hex   )sysversion_infointencode)valuer0   r0   r1   _func  s    z.Instance.generate_root_password.<locals>._funcrW   c                s    g | ]}t  |tt   qS r0   )PASSWORD_CHARSlen)ri   rj   )r   r0   r1   rk     s   z3Instance.generate_root_password.<locals>.<listcomp>2   n   )joinr   r   r   )rA   r0   )r   r1   rC     s    
zInstance.generate_root_passwordc                sF  ddl m} | jdkrdndfddtdd	D   fd
dtdt D }|rf|s^|rftd|s4t|ts||g}t|ts|g}g }xP|D ]H}	|	dkr|d qt|	t	r||	 q|t	| j
t|	| j qW xP|D ]H}
|
dkr|d qt|
|r||
 q||| j
t|
 qW |sBtdxjt|D ]^\}}	|	dkr`nHt|	t	rd|	ji| | < n(t|	|rd|	ji| | < ntdqLW tt|tr|jn||r|nd| jt| j|d}|| | j
jdtj| |d}|   d|kr,td|dt| j
|d | j|}|S )a  
        Creates a Linode Config with the given attributes.

        :param kernel: The kernel to boot with.
        :param label: The config label
        :param disks: The list of disks, starting at sda, to map to this config.
        :param volumes: The volumes, starting after the last disk, to map to this
            config
        :param devices: A list of devices to assign to this config, in device
            index order.  Values must be of type Disk or Volume. If this is
            given, you may not include disks or volumes.
        :param **kwargs: Any other arguments accepted by the api.

        :returns: A new Linode Config
        re   )rf   rK   sdZxvdc                s   g | ]} t j|  qS r0   )stringascii_lowercase)ri   r   )hypervisor_prefixr0   r1   rk     s    z*Instance.config_create.<locals>.<listcomp>r      c                s   i | ]}d  | qS )Nr0   )ri   r   )device_namesr0   r1   
<dictcomp>  s    z*Instance.config_create.<locals>.<dictcomp>z[You may not call config_create with "devices" and either of "disks" or "volumes" specified!Nz)Must include at least one disk or volume!rg   rh   zDisk or Volume expected!z{}_config_{})ra   r!   rb   z
{}/configs)r%   r&   r   z$Unexpected response creating config!)r>   )rl   rf   rw   r   r   
ValueErrorrp   r   rq   r9   r)   r   r   	enumerate	TypeErrorr'   r    r   r+   r!   r"   r(   r*   rB   r,   r   r   r_   )r-   ra   r!   rb   r#   Zvolumesr.   rf   Z
device_mapr/   vr   rE   r?   rj   r0   )r   r   r1   config_create  sX    








zInstance.config_createFc
             K   s   d}|r|st  }|}t|}|r4|s4d|j}||r>|nd| jt| j||||d}|r|tt	|t
rz|jn||d |	r|	j|d< |
r|
|d< | jjdt j| |d	}|   d
|krtd|dt| j|d
 | j|}|r||fS |S )a2  
        Creates a new Disk for this Instance.

        :param size: The size of the disk, in MB
        :param label: The label of the disk.  If not given, a default label will be generated.
        :param filesystem: The filesystem type for the disk.  If not given, the default
                           for the image deployed the disk will be used.  Required
                           if creating a disk without an image.
        :param read_only: If True, creates a read-only disk
        :param image: The Image to deploy to the disk.
        :param root_pass: The password to configure for the root user when deploying an
                          image to this disk.  Not used if image is not given.  If an
                          image is given and root_pass is not, a password will be
                          generated and returned alongside the new disk.
        :param authorized_keys: A list of SSH keys to install as trusted for the root user.
        :param authorized_users: A list of usernames whose keys should be installed
                                 as trusted for the root user.  These user's keys
                                 should already be set up, see :any:`ProfileGroup.ssh_keys`
                                 for details.
        :param stackscript: A StackScript object, or the ID of one, to deploy to this
                            disk.  Requires deploying a compatible image.
        :param **stackscript_args: Any arguments to pass to the StackScript, as defined
                                   by its User Defined Fields.
        Nz
My {} Diskz
{}_disk_{})r<   r!   	read_onlyr=   authorized_keysauthorized_users)rt   	root_passZstackscript_idZstackscript_dataz{}/disks)r%   r&   r   z"Unexpected response creating disk!)r>   )rB   rC   r   r+   r!   r   r#   r(   r'   r    r   r   r)   r*   r,   r   r   r9   )r-   r<   r!   r=   r   rt   r   r   r   ZstackscriptZstackscript_argsZgen_passrE   r?   r/   r0   r0   r1   disk_create5  s:    

zInstance.disk_createc             C   s$   | j jdtj| d |   dS )aJ  
        Enable Backups for this Instance.  When enabled, we will automatically
        backup your Instance's data so that it can be restored at a later date.
        For more information on Instance's Backups service and pricing, see our
        `Backups Page`_

        .. _Backups Page: https://www.linode.com/backups
        z{}/backups/enable)r%   T)r)   r*   r+   rB   r,   r   )r-   r0   r0   r1   enable_backupsz  s    	zInstance.enable_backupsc             C   s$   | j jdtj| d |   dS )z
        Cancels Backups for this Instance.  All existing Backups will be lost,
        including any snapshots that have been taken.  This cannot be undone,
        but Backups can be re-enabled at a later date.
        z{}/backups/cancel)r%   T)r)   r*   r+   rB   r,   r   )r-   r0   r0   r1   cancel_backups  s    zInstance.cancel_backupsc             C   sZ   | j jdtj| d|id}d|kr2td|dt| dr@| `t| j |d | j	|}|S )Nz
{}/backupsr!   )r%   r&   r   z$Unexpected response taking snapshot!)r>   r   )
r)   r*   r+   rB   r,   r   r   r   r   r   )r-   r!   r?   br0   r0   r1   r     s    
zInstance.snapshotc             C   sJ   | j jdtj| d|dd}d|kr4td|dt| j |d |}|S )a  
        Allocates a new :any:`IPAddress` for this Instance.  Additional public
        IPs require justification, and you may need to open a :any:`SupportTicket`
        before you can add one.  You may only have, at most, one private IP per
        Instance.

        :param public: If the new IP should be public or private.  Defaults to
                       private.
        :type public: bool

        :returns: The new IPAddress
        :rtype: IPAddress
        z{}/ipsru   )r    r[   )r%   r&   r{   z"Unexpected response allocating IP!)r>   )r)   r*   r+   rB   r,   r   r   )r-   r[   r?   r   r0   r0   r1   ip_allocate  s    
zInstance.ip_allocatec             K   s   d}|st  }|}t|}tt|tr0|jn|||d}|| | jj	d
t j| |d}d|krttd|d| | |sdS |S dS )	a  
        Rebuilding an Instance deletes all existing Disks and Configs and deploys
        a new :any:`Image` to it.  This can be used to reset an existing
        Instance or to install an Image on an empty Instance.

        :param image: The Image to deploy to this Instance
        :type image: str or Image
        :param root_pass: The root password for the newly rebuilt Instance.  If
                          omitted, a password will be generated and returned.
        :type root_pass: str
        :param authorized_keys: The ssh public keys to install in the linode's
                                /root/.ssh/authorized_keys file.  Each entry may
                                be a single key, or a path to a file containing
                                the key.
        :type authorized_keys: list or str

        :returns: The newly generated password, if one was not provided
                  (otherwise True)
        :rtype: str or bool
        N)rt   r   r   z
{}/rebuild)r%   r&   r   z$Unexpected response issuing rebuild!)r>   T)rB   rC   r   r'   r    r   r   r(   r)   r*   r+   r,   r   rD   )r-   rt   r   r   r.   Zret_passrE   r?   r0   r0   r1   rebuild  s     

zInstance.rebuildc             G   s@   |rdd t d|D }nd }| jjdtj| d|id}|S )Nc             S   s   i | ]\}}d |i|qS )rg   r0   )ri   xyr0   r0   r1   r     s    z#Instance.rescue.<locals>.<dictcomp>)ZsdaZsdbZsdcZsddZsdeZsdfZsdgz	{}/rescuerb   )r%   r&   )zipr)   r*   r+   rB   r,   )r-   r#   r?   r0   r0   r1   rescue  s    zInstance.rescuec             C   s   | j jdtj| d dS )z6
        Converts this linode to KVM from Xen
        z	{}/kvmify)r%   T)r)   r*   r+   rB   r,   )r-   r0   r0   r1   kvmify  s    zInstance.kvmifyc             C   s   | j jdtj| d dS )zF
        Upgrades this Instance to the latest generation type
        z	{}/mutate)r%   T)r)   r*   r+   rB   r,   )r-   r0   r0   r1   mutate  s    zInstance.mutatec             C   s   | j jdtj| d dS )zj
        Initiates a pending migration that is already scheduled for this Linode
        Instance
        z
{}/migrate)r%   N)r)   r*   r+   rB   r,   )r-   r0   r0   r1   initiate_migration  s    zInstance.initiate_migrationc	          	   C   s  |r|rt d|r |s t dt|ts:t|ts:|g}t|tsTt|tsT|g}dd |D }	dd |D }
tt|tr|jn|tt|tr|jn|tt|tr|jn||	r|	nd|
r|
nd|||d}| jj	d
tj| |d	}d
|krtd|dt| j|d
 |}|S )zO Clones this linode into a new linode or into a new linode in the given region z4You may only specify one of "to_linode" and "region"z0Specifying a region requires a "service" as wellc             S   s$   g | ]}t t|tr|jn|qS r0   )r'   r    r   r   )ri   rj   r0   r0   r1   rk     s    z"Instance.clone.<locals>.<listcomp>c             S   s$   g | ]}t t|tr|jn|qS r0   )r'   r    r   r   )ri   r/   r0   r0   r1   rk     s    N)r   r$   r    r"   r#   r!   rs   with_backupsz{}/clone)r%   r&   r   z%Unexpected response cloning Instance!)r>   )r   rp   r   r   r'   r    r   r   r)   r*   r+   rB   r,   r   )r-   Z	to_linoder$   Zservicer"   r#   r!   rs   r   ZcidsZdidsrE   r?   lr0   r0   r1   clone  s.    


zInstance.clonec             C   s   | j jdtj| dS )z:
        Returns the JSON stats for this Instance
        z{}/stats)r%   )r)   r   r+   rB   r,   )r-   r0   r0   r1   stats2  s    zInstance.statsc             C   s2   t |tstd| jjdtj|d| dS )zK
        Returns stats for the month containing the given datetime
        z%stats_for requires a datetime object!z{}/stats/{}z%Y/%m)r%   )	rp   r   r   r)   r   r+   rB   r,   strftime)r-   dtr0   r0   r1   	stats_for:  s    
zInstance.stats_for)N)NNFNNNNN)N)F)NN)%r3   r4   r5   r,   r   r   r
   r9   r_   rN   r8   propertyr   r   rO   rD   r   r   r   r   rG   staticmethodrC   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r0   r0   r0   r1   rB     s\   





5$
P 
D



0
#rB   c               @   s   e Zd ZdZdZdZdS )UserDefinedFieldTypere      r   N)r3   r4   r5   text
select_oneselect_manyr0   r0   r0   r1   r   D  s   r   c               @   s   e Zd ZdddZdd ZdS )UserDefinedFieldNc             C   s"   || _ || _|| _|| _|| _d S )N)namer!   example
field_typechoices)r-   r   r!   r   r   r   r0   r0   r1   rZ   J  s
    zUserDefinedField.__init__c             C   s   d | j| jj| jS )Nz
{}({}): {})r+   r!   r   r   r   )r-   r0   r0   r1   r\   Q  s    zUserDefinedField.__repr__)N)r3   r4   r5   rZ   r\   r0   r0   r0   r1   r   I  s   
r   c               @   s   e Zd ZdZe edddeddedde edddedde eddeddde edddedddZdd	 Zd
d ZdS )StackScriptz/linode/stackscripts/{id}T)r:   r;   )r:   )r;   )r   )user_defined_fieldsr!   Zrev_noteusernameZuser_gravatar_idZ	is_publicr   Zdeployments_activescriptimagesZdeployments_totalrJ   r   c          
      s   t  | g }x jD ]}tj}d}t|drDtj}|jd}nt|dr`tj	}|j
d}|t|jt|drz|jndt|dr|jnd||d qW  d|  fd	d
 jD } d| dS )za
        Override the populate method to map user_defined_fields to
        fancy values
        Noneof,manyofr!   r   )r   r   c                s   g | ]}t  j|qS r0   )r
   r)   )ri   r/   )r-   r0   r1   rk   ~  s    z)StackScript._populate.<locals>.<listcomp>r   )r   rD   r   r   r   r   r   r   splitr   r   rq   r   r   r!   r   rn   r   )r-   r>   Zmapped_udfsZudftr   Zndistr0   )r-   r1   rD   f  s$    


zStackScript._populatec             C   s"   t | }dd | jD |d< |S )Nc             S   s   g | ]
}|j qS r0   )r   )ri   r/   r0   r0   r1   rk     s    z*StackScript._serialize.<locals>.<listcomp>r   )r   r]   r   )r-   dctr0   r0   r1   r]     s    
zStackScript._serializeN)r3   r4   r5   r,   r   r8   rD   r]   r0   r0   r0   r1   r   T  s    



r   )*r   r   r   enumr   osr   randomr   Zlinode_api4.commonr   Zlinode_api4.errorsr   Zlinode_api4.objectsr   r	   r
   r   r   Zlinode_api4.objects.baser   Zlinode_api4.objects.filteringr   Zlinode_api4.objects.networkingr   r   Zlinode_api4.paginated_listr   ascii_lettersdigitspunctuationr   r   r9   rH   rN   rV   r_   rB   r   r   r   r0   r0   r0   r1   <module>   s6    C'K    1