signature:
def create ( self , * args , ** kwargs ) :
    """Create the droplet with object properties .
 Note : Every argument and parameter given to this method will be
 assigned to the object ."""

implementation:
for attr in kwargs . keys ( ) :
    setattr ( self , attr , kwargs [ attr ] )
# Provide backwards compatibility
if not self . size_slug and self . size :
    self . size_slug = self . size
ssh_keys_id = Droplet . __get_ssh_keys_id_or_fingerprint ( self . ssh_keys , self . token , self . name )
data = { "name" : self . name , "size" : self . size_slug , "image" : self . image , "region" : self . region , "ssh_keys" : ssh_keys_id , "backups" : bool ( self . backups ) , "ipv6" : bool ( self . ipv6 ) , "private_networking" : bool ( self . private_networking ) , "volumes" : self . volumes , "tags" : self . tags , "monitoring" : bool ( self . monitoring ) , }
if self . user_data :
    data [ "user_data" ] = self . user_data
data = self . get_data ( "droplets/" , type = POST , params = data )
if data :
    self . id = data [ 'droplet' ] [ 'id' ]
    action_id = data [ 'links' ] [ 'actions' ] [ 0 ] [ 'id' ]
    self . action_ids = [ ]
    self . action_ids . append ( action_id )


signature:
def get_actions ( self ) :
    """Returns a list of Action objects
 This actions can be used to check the droplet ' s status"""

implementation:
answer = self . get_data ( "droplets/%s/actions/" % self . id , type = GET )
actions = [ ]
for action_dict in answer [ 'actions' ] :
    action = Action ( ** action_dict )
    action . token = self . token
    action . droplet_id = self . id
    action . load ( )
    actions . append ( action )
return actions


signature:
def get_action ( self , action_id ) :
    """Returns a specific Action by its ID .
 Args :
 action _ id ( int ) : id of action"""

implementation: return Action . get_object ( api_token = self . token , action_id = action_id )


signature:
def get_snapshots ( self ) :
    """This method will return the snapshots / images connected to that
 specific droplet ."""

implementation:
snapshots = list ( )
for id in self . snapshot_ids :
    snapshot = Image ( )
    snapshot . id = id
    snapshot . token = self . token
    snapshots . append ( snapshot )
return snapshots


signature:
def get_kernel_available ( self ) :
    """Get a list of kernels available"""

implementation:
kernels = list ( )
data = self . get_data ( "droplets/%s/kernels/" % self . id )
while True :
    for jsond in data [ u'kernels' ] :
        kernel = Kernel ( ** jsond )
        kernel . token = self . token
        kernels . append ( kernel )
    try :
        url = data [ u'links' ] [ u'pages' ] . get ( u'next' )
        if not url :
            break
        data = self . get_data ( url )
    except KeyError : # No links .
        break
return kernels


signature:
def get_object ( cls , api_token , domain_name ) :
    """Class method that will return a Domain object by ID ."""

implementation:
domain = cls ( token = api_token , name = domain_name )
domain . load ( )
return domain


signature:
def create_new_domain_record ( self , * args , ** kwargs ) :
    """Create new domain record .
 https : / / developers . digitalocean . com / # create - a - new - domain - record
 Args :
 type : The record type ( A , MX , CNAME , etc ) .
 name : The host name , alias , or service being defined by the record
 data : Variable data depending on record type .
 Optional Args :
 priority : The priority of the host
 port : The port that the service is accessible on
 weight : The weight of records with the same priority"""

implementation:
data = { "type" : kwargs . get ( "type" , None ) , "name" : kwargs . get ( "name" , None ) , "data" : kwargs . get ( "data" , None ) }
# Optional Args
if kwargs . get ( "priority" , None ) :
    data [ 'priority' ] = kwargs . get ( "priority" , None )
if kwargs . get ( "port" , None ) :
    data [ 'port' ] = kwargs . get ( "port" , None )
if kwargs . get ( "weight" , None ) :
    data [ 'weight' ] = kwargs . get ( "weight" , None )
return self . get_data ( "domains/%s/records" % self . name , type = POST , params = data )


signature:
def create ( self ) :
    """Create new doamin"""

implementation:
# URL https : / / api . digitalocean . com / v2 / domains
data = { "name" : self . name , "ip_address" : self . ip_address , }
domain = self . get_data ( "domains" , type = POST , params = data )
return domain


signature:
def get_records ( self , params = None ) :
    """Returns a list of Record objects"""

implementation:
if params is None :
    params = { }
# URL https : / / api . digitalocean . com / v2 / domains / [ NAME ] / records /
records = [ ]
data = self . get_data ( "domains/%s/records/" % self . name , type = GET , params = params )
for record_data in data [ 'domain_records' ] :
    record = Record ( domain_name = self . name , ** record_data )
    record . token = self . token
    records . append ( record )
return records


signature:
def get_object ( cls , api_token ) :
    """Class method that will return an Account object ."""

implementation:
acct = cls ( token = api_token )
acct . load ( )
return acct


signature:
def get_object ( cls , api_token , ip ) :
    """Class method that will return a FloatingIP object by its IP .
 Args :
 api _ token : str - token
 ip : str - floating ip address"""

implementation:
floating_ip = cls ( token = api_token , ip = ip )
floating_ip . load ( )
return floating_ip


signature:
def load ( self ) :
    """Load the FloatingIP object from DigitalOcean .
 Requires self . ip to be set ."""

implementation:
data = self . get_data ( 'floating_ips/%s' % self . ip , type = GET )
floating_ip = data [ 'floating_ip' ]
# Setting the attribute values
for attr in floating_ip . keys ( ) :
    setattr ( self , attr , floating_ip [ attr ] )
return self


signature:
def create ( self , * args , ** kwargs ) :
    """Creates a FloatingIP and assigns it to a Droplet .
 Note : Every argument and parameter given to this method will be
 assigned to the object .
 Args :
 droplet _ id : int - droplet id"""

implementation:
data = self . get_data ( 'floating_ips/' , type = POST , params = { 'droplet_id' : self . droplet_id } )
if data :
    self . ip = data [ 'floating_ip' ] [ 'ip' ]
    self . region = data [ 'floating_ip' ] [ 'region' ]
return self


signature:
def reserve ( self , * args , ** kwargs ) :
    """Creates a FloatingIP in a region without assigning
 it to a specific Droplet .
 Note : Every argument and parameter given to this method will be
 assigned to the object .
 Args :
 region _ slug : str - region ' s slug ( e . g . ' nyc3 ' )"""

implementation:
data = self . get_data ( 'floating_ips/' , type = POST , params = { 'region' : self . region_slug } )
if data :
    self . ip = data [ 'floating_ip' ] [ 'ip' ]
    self . region = data [ 'floating_ip' ] [ 'region' ]
return self


signature:
def assign ( self , droplet_id ) :
    """Assign a FloatingIP to a Droplet .
 Args :
 droplet _ id : int - droplet id"""

implementation: return self . get_data ( "floating_ips/%s/actions/" % self . ip , type = POST , params = { "type" : "assign" , "droplet_id" : droplet_id } )


signature:
def get_object ( cls , api_token , firewall_id ) :
    """Class method that will return a Firewall object by ID ."""

implementation:
firewall = cls ( token = api_token , id = firewall_id )
firewall . load ( )
return firewall


signature:
def add_tags ( self , tags ) :
    """Add tags to this Firewall ."""

implementation: return self . get_data ( "firewalls/%s/tags" % self . id , type = POST , params = { "tags" : tags } )


signature:
def remove_tags ( self , tags ) :
    """Remove tags from this Firewall ."""

implementation: return self . get_data ( "firewalls/%s/tags" % self . id , type = DELETE , params = { "tags" : tags } )


signature:
def get_object ( cls , api_token , ssh_key_id ) :
    """Class method that will return a SSHKey object by ID ."""

implementation:
ssh_key = cls ( token = api_token , id = ssh_key_id )
ssh_key . load ( )
return ssh_key


signature:
def load ( self ) :
    """Load the SSHKey object from DigitalOcean .
 Requires either self . id or self . fingerprint to be set ."""

implementation:
identifier = None
if self . id :
    identifier = self . id
elif self . fingerprint is not None :
    identifier = self . fingerprint
data = self . get_data ( "account/keys/%s" % identifier , type = GET )
ssh_key = data [ 'ssh_key' ]
# Setting the attribute values
for attr in ssh_key . keys ( ) :
    setattr ( self , attr , ssh_key [ attr ] )
self . id = ssh_key [ 'id' ]


signature:
def load_by_pub_key ( self , public_key ) :
    """This method will load a SSHKey object from DigitalOcean
 from a public _ key . This method will avoid problems like
 uploading the same public _ key twice ."""

implementation:
data = self . get_data ( "account/keys/" )
for jsoned in data [ 'ssh_keys' ] :
    if jsoned . get ( 'public_key' , "" ) == public_key :
        self . id = jsoned [ 'id' ]
        self . load ( )
        return self
return None


signature:
def create ( self ) :
    """Create the SSH Key"""

implementation:
input_params = { "name" : self . name , "public_key" : self . public_key , }
data = self . get_data ( "account/keys/" , type = POST , params = input_params )
if data :
    self . id = data [ 'ssh_key' ] [ 'id' ]


signature:
def edit ( self ) :
    """Edit the SSH Key"""

implementation:
input_params = { "name" : self . name , "public_key" : self . public_key , }
data = self . get_data ( "account/keys/%s" % self . id , type = PUT , params = input_params )
if data :
    self . id = data [ 'ssh_key' ] [ 'id' ]


signature:
def get_all_regions ( self ) :
    """This function returns a list of Region object ."""

implementation:
data = self . get_data ( "regions/" )
regions = list ( )
for jsoned in data [ 'regions' ] :
    region = Region ( ** jsoned )
    region . token = self . token
    regions . append ( region )
return regions


signature:
def get_all_droplets ( self , tag_name = None ) :
    """This function returns a list of Droplet object ."""

implementation:
params = dict ( )
if tag_name :
    params [ "tag_name" ] = tag_name
data = self . get_data ( "droplets/" , params = params )
droplets = list ( )
for jsoned in data [ 'droplets' ] :
    droplet = Droplet ( ** jsoned )
    droplet . token = self . token
    for net in droplet . networks [ 'v4' ] :
        if net [ 'type' ] == 'private' :
            droplet . private_ip_address = net [ 'ip_address' ]
        if net [ 'type' ] == 'public' :
            droplet . ip_address = net [ 'ip_address' ]
    if droplet . networks [ 'v6' ] :
        droplet . ip_v6_address = droplet . networks [ 'v6' ] [ 0 ] [ 'ip_address' ]
    if "backups" in droplet . features :
        droplet . backups = True
    else :
        droplet . backups = False
    if "ipv6" in droplet . features :
        droplet . ipv6 = True
    else :
        droplet . ipv6 = False
    if "private_networking" in droplet . features :
        droplet . private_networking = True
    else :
        droplet . private_networking = False
    droplets . append ( droplet )
return droplets


signature:
def get_droplet ( self , droplet_id ) :
    """Return a Droplet by its ID ."""

implementation: return Droplet . get_object ( api_token = self . token , droplet_id = droplet_id )


signature:
def get_all_sizes ( self ) :
    """This function returns a list of Size object ."""

implementation:
data = self . get_data ( "sizes/" )
sizes = list ( )
for jsoned in data [ 'sizes' ] :
    size = Size ( ** jsoned )
    size . token = self . token
    sizes . append ( size )
return sizes


signature:
def get_images ( self , private = False , type = None ) :
    """This function returns a list of Image object ."""

implementation:
params = { }
if private :
    params [ 'private' ] = 'true'
if type :
    params [ 'type' ] = type
data = self . get_data ( "images/" , params = params )
images = list ( )
for jsoned in data [ 'images' ] :
    image = Image ( ** jsoned )
    image . token = self . token
    images . append ( image )
return images


signature:
def get_image ( self , image_id_or_slug ) :
    """Return a Image by its ID / Slug ."""

implementation: return Image . get_object ( api_token = self . token , image_id_or_slug = image_id_or_slug , )


signature:
def get_global_images ( self ) :
    """This function returns a list of Image objects representing
 public DigitalOcean images ( e . g . base distribution images
 and ' One - Click ' applications ) ."""

implementation:
data = self . get_images ( )
images = list ( )
for i in data :
    if i . public :
        i . token = self . token
        images . append ( i )
return images


signature:
def get_all_domains ( self ) :
    """This function returns a list of Domain object ."""

implementation:
data = self . get_data ( "domains/" )
domains = list ( )
for jsoned in data [ 'domains' ] :
    domain = Domain ( ** jsoned )
    domain . token = self . token
    domains . append ( domain )
return domains


signature:
def get_domain ( self , domain_name ) :
    """Return a Domain by its domain _ name"""

implementation: return Domain . get_object ( api_token = self . token , domain_name = domain_name )


signature:
def get_all_sshkeys ( self ) :
    """This function returns a list of SSHKey object ."""

implementation:
data = self . get_data ( "account/keys/" )
ssh_keys = list ( )
for jsoned in data [ 'ssh_keys' ] :
    ssh_key = SSHKey ( ** jsoned )
    ssh_key . token = self . token
    ssh_keys . append ( ssh_key )
return ssh_keys


signature:
def get_ssh_key ( self , ssh_key_id ) :
    """Return a SSHKey object by its ID ."""

implementation: return SSHKey . get_object ( api_token = self . token , ssh_key_id = ssh_key_id )


signature:
def get_all_tags ( self ) :
    """This method returns a list of all tags ."""

implementation:
data = self . get_data ( "tags" )
return [ Tag ( token = self . token , ** tag ) for tag in data [ 'tags' ] ]


signature:
def get_all_floating_ips ( self ) :
    """This function returns a list of FloatingIP objects ."""

implementation:
data = self . get_data ( "floating_ips" )
floating_ips = list ( )
for jsoned in data [ 'floating_ips' ] :
    floating_ip = FloatingIP ( ** jsoned )
    floating_ip . token = self . token
    floating_ips . append ( floating_ip )
return floating_ips


signature:
def get_floating_ip ( self , ip ) :
    """Returns a of FloatingIP object by its IP address ."""

implementation: return FloatingIP . get_object ( api_token = self . token , ip = ip )


signature:
def get_all_load_balancers ( self ) :
    """Returns a list of Load Balancer objects ."""

implementation:
data = self . get_data ( "load_balancers" )
load_balancers = list ( )
for jsoned in data [ 'load_balancers' ] :
    load_balancer = LoadBalancer ( ** jsoned )
    load_balancer . token = self . token
    load_balancer . health_check = HealthCheck ( ** jsoned [ 'health_check' ] )
    load_balancer . sticky_sessions = StickySesions ( ** jsoned [ 'sticky_sessions' ] )
    forwarding_rules = list ( )
    for rule in jsoned [ 'forwarding_rules' ] :
        forwarding_rules . append ( ForwardingRule ( ** rule ) )
    load_balancer . forwarding_rules = forwarding_rules
    load_balancers . append ( load_balancer )
return load_balancers


signature:
def get_load_balancer ( self , id ) :
    """Returns a Load Balancer object by its ID .
 Args :
 id ( str ) : Load Balancer ID"""

implementation: return LoadBalancer . get_object ( api_token = self . token , id = id )


signature:
def get_certificate ( self , id ) :
    """Returns a Certificate object by its ID .
 Args :
 id ( str ) : Certificate ID"""

implementation: return Certificate . get_object ( api_token = self . token , cert_id = id )


signature:
def get_all_certificates ( self ) :
    """This function returns a list of Certificate objects ."""

implementation:
data = self . get_data ( "certificates" )
certificates = list ( )
for jsoned in data [ 'certificates' ] :
    cert = Certificate ( ** jsoned )
    cert . token = self . token
    certificates . append ( cert )
return certificates


signature:
def get_snapshot ( self , snapshot_id ) :
    """Return a Snapshot by its ID ."""

implementation: return Snapshot . get_object ( api_token = self . token , snapshot_id = snapshot_id )


signature:
def get_all_snapshots ( self ) :
    """This method returns a list of all Snapshots ."""

implementation:
data = self . get_data ( "snapshots/" )
return [ Snapshot ( token = self . token , ** snapshot ) for snapshot in data [ 'snapshots' ] ]


signature:
def get_droplet_snapshots ( self ) :
    """This method returns a list of all Snapshots based on Droplets ."""

implementation:
data = self . get_data ( "snapshots?resource_type=droplet" )
return [ Snapshot ( token = self . token , ** snapshot ) for snapshot in data [ 'snapshots' ] ]


signature:
def get_volume_snapshots ( self ) :
    """This method returns a list of all Snapshots based on volumes ."""

implementation:
data = self . get_data ( "snapshots?resource_type=volume" )
return [ Snapshot ( token = self . token , ** snapshot ) for snapshot in data [ 'snapshots' ] ]


signature:
def get_all_volumes ( self , region = None ) :
    """This function returns a list of Volume objects ."""

implementation:
if region :
    url = "volumes?region={}" . format ( region )
else :
    url = "volumes"
data = self . get_data ( url )
volumes = list ( )
for jsoned in data [ 'volumes' ] :
    volume = Volume ( ** jsoned )
    volume . token = self . token
    volumes . append ( volume )
return volumes


signature:
def get_volume ( self , volume_id ) :
    """Returns a Volume object by its ID ."""

implementation: return Volume . get_object ( api_token = self . token , volume_id = volume_id )


signature:
def get_all_firewalls ( self ) :
    """This function returns a list of Firewall objects ."""

implementation:
data = self . get_data ( "firewalls" )
firewalls = list ( )
for jsoned in data [ 'firewalls' ] :
    firewall = Firewall ( ** jsoned )
    firewall . token = self . token
    in_rules = list ( )
    for rule in jsoned [ 'inbound_rules' ] :
        in_rules . append ( InboundRule ( ** rule ) )
    firewall . inbound_rules = in_rules
    out_rules = list ( )
    for rule in jsoned [ 'outbound_rules' ] :
        out_rules . append ( OutboundRule ( ** rule ) )
    firewall . outbound_rules = out_rules
    firewalls . append ( firewall )
return firewalls


signature:
def get_firewall ( self , firewall_id ) :
    """Return a Firewall by its ID ."""

implementation: return Firewall . get_object ( api_token = self . token , firewall_id = firewall_id , )


signature:
def get_object ( cls , api_token , id ) :
    """Class method that will return a LoadBalancer object by its ID .
 Args :
 api _ token ( str ) : DigitalOcean API token
 id ( str ) : Load Balancer ID"""

implementation:
load_balancer = cls ( token = api_token , id = id )
load_balancer . load ( )
return load_balancer


signature:
def load ( self ) :
    """Loads updated attributues for a LoadBalancer object .
 Requires self . id to be set ."""

implementation:
data = self . get_data ( 'load_balancers/%s' % self . id , type = GET )
load_balancer = data [ 'load_balancer' ]
# Setting the attribute values
for attr in load_balancer . keys ( ) :
    if attr == 'health_check' :
        health_check = HealthCheck ( ** load_balancer [ 'health_check' ] )
        setattr ( self , attr , health_check )
    elif attr == 'sticky_sessions' :
        sticky_ses = StickySesions ( ** load_balancer [ 'sticky_sessions' ] )
        setattr ( self , attr , sticky_ses )
    elif attr == 'forwarding_rules' :
        rules = list ( )
        for rule in load_balancer [ 'forwarding_rules' ] :
            rules . append ( ForwardingRule ( ** rule ) )
        setattr ( self , attr , rules )
    else :
        setattr ( self , attr , load_balancer [ attr ] )
return self


signature:
def create ( self , * args , ** kwargs ) :
    """Creates a new LoadBalancer .
 Note : Every argument and parameter given to this method will be
 assigned to the object .
 Args :
 name ( str ) : The Load Balancer ' s name
 region ( str ) : The slug identifier for a DigitalOcean region
 algorithm ( str , optional ) : The load balancing algorithm to be
 used . Currently , it must be either " round _ robin " or
 " least _ connections "
 forwarding _ rules ( obj : ` list ` ) : A list of ` ForwrdingRules ` objects
 health _ check ( obj , optional ) : A ` HealthCheck ` object
 sticky _ sessions ( obj , optional ) : A ` StickySessions ` object
 redirect _ http _ to _ https ( bool , optional ) : A boolean indicating
 whether HTTP requests to the Load Balancer should be
 redirected to HTTPS
 droplet _ ids ( obj : ` list ` of ` int ` ) : A list of IDs representing
 Droplets to be added to the Load Balancer ( mutually
 exclusive with ' tag ' )
 tag ( str ) : A string representing a DigitalOcean Droplet tag
 ( mutually exclusive with ' droplet _ ids ' )"""

implementation:
rules_dict = [ rule . __dict__ for rule in self . forwarding_rules ]
params = { 'name' : self . name , 'region' : self . region , 'forwarding_rules' : rules_dict , 'redirect_http_to_https' : self . redirect_http_to_https }
if self . droplet_ids and self . tag :
    raise ValueError ( 'droplet_ids and tag are mutually exclusive args' )
elif self . tag :
    params [ 'tag' ] = self . tag
else :
    params [ 'droplet_ids' ] = self . droplet_ids
if self . algorithm :
    params [ 'algorithm' ] = self . algorithm
if self . health_check :
    params [ 'health_check' ] = self . health_check . __dict__
if self . sticky_sessions :
    params [ 'sticky_sessions' ] = self . sticky_sessions . __dict__
data = self . get_data ( 'load_balancers/' , type = POST , params = params )
if data :
    self . id = data [ 'load_balancer' ] [ 'id' ]
    self . ip = data [ 'load_balancer' ] [ 'ip' ]
    self . algorithm = data [ 'load_balancer' ] [ 'algorithm' ]
    self . health_check = HealthCheck ( ** data [ 'load_balancer' ] [ 'health_check' ] )
    self . sticky_sessions = StickySesions ( ** data [ 'load_balancer' ] [ 'sticky_sessions' ] )
    self . droplet_ids = data [ 'load_balancer' ] [ 'droplet_ids' ]
    self . status = data [ 'load_balancer' ] [ 'status' ]
    self . created_at = data [ 'load_balancer' ] [ 'created_at' ]
return self


signature:
def save ( self ) :
    """Save the LoadBalancer"""

implementation:
forwarding_rules = [ rule . __dict__ for rule in self . forwarding_rules ]
data = { 'name' : self . name , 'region' : self . region [ 'slug' ] , 'forwarding_rules' : forwarding_rules , 'redirect_http_to_https' : self . redirect_http_to_https }
if self . tag :
    data [ 'tag' ] = self . tag
else :
    data [ 'droplet_ids' ] = self . droplet_ids
if self . algorithm :
    data [ "algorithm" ] = self . algorithm
if self . health_check :
    data [ 'health_check' ] = self . health_check . __dict__
if self . sticky_sessions :
    data [ 'sticky_sessions' ] = self . sticky_sessions . __dict__
return self . get_data ( "load_balancers/%s/" % self . id , type = PUT , params = data )


signature:
def add_droplets ( self , droplet_ids ) :
    """Assign a LoadBalancer to a Droplet .
 Args :
 droplet _ ids ( obj : ` list ` of ` int ` ) : A list of Droplet IDs"""

implementation: return self . get_data ( "load_balancers/%s/droplets/" % self . id , type = POST , params = { "droplet_ids" : droplet_ids } )


signature:
def remove_droplets ( self , droplet_ids ) :
    """Unassign a LoadBalancer .
 Args :
 droplet _ ids ( obj : ` list ` of ` int ` ) : A list of Droplet IDs"""

implementation: return self . get_data ( "load_balancers/%s/droplets/" % self . id , type = DELETE , params = { "droplet_ids" : droplet_ids } )


signature:
def add_forwarding_rules ( self , forwarding_rules ) :
    """Adds new forwarding rules to a LoadBalancer .
 Args :
 forwarding _ rules ( obj : ` list ` ) : A list of ` ForwrdingRules ` objects"""

implementation:
rules_dict = [ rule . __dict__ for rule in forwarding_rules ]
return self . get_data ( "load_balancers/%s/forwarding_rules/" % self . id , type = POST , params = { "forwarding_rules" : rules_dict } )


signature:
def remove_forwarding_rules ( self , forwarding_rules ) :
    """Removes existing forwarding rules from a LoadBalancer .
 Args :
 forwarding _ rules ( obj : ` list ` ) : A list of ` ForwrdingRules ` objects"""

implementation:
rules_dict = [ rule . __dict__ for rule in forwarding_rules ]
return self . get_data ( "load_balancers/%s/forwarding_rules/" % self . id , type = DELETE , params = { "forwarding_rules" : rules_dict } )


signature:
def get_data ( self , url , headers = dict ( ) , params = dict ( ) , render_json = True ) :
    """Customized version of get _ data to directly get the data without
 using the authentication method ."""

implementation:
url = urljoin ( self . end_point , url )
response = requests . get ( url , headers = headers , params = params , timeout = self . get_timeout ( ) )
if render_json :
    return response . json ( )
return response . content


signature:
def get_object ( cls , api_token , domain , record_id ) :
    """Class method that will return a Record object by ID and the domain ."""

implementation:
record = cls ( token = api_token , domain = domain , id = record_id )
record . load ( )
return record


signature:
def create ( self ) :
    """Creates a new record for a domain .
 Args :
 type ( str ) : The type of the DNS record ( e . g . A , CNAME , TXT ) .
 name ( str ) : The host name , alias , or service being defined by the
 record .
 data ( int ) : Variable data depending on record type .
 priority ( int ) : The priority for SRV and MX records .
 port ( int ) : The port for SRV records .
 ttl ( int ) : The time to live for the record , in seconds .
 weight ( int ) : The weight for SRV records .
 flags ( int ) : An unsigned integer between 0-255 used for CAA records .
 tags ( string ) : The parameter tag for CAA records . Valid values are
 " issue " , " wildissue " , or " iodef " """

implementation:
input_params = { "type" : self . type , "data" : self . data , "name" : self . name , "priority" : self . priority , "port" : self . port , "ttl" : self . ttl , "weight" : self . weight , "flags" : self . flags , "tags" : self . tags }
data = self . get_data ( "domains/%s/records" % ( self . domain ) , type = POST , params = input_params , )
if data :
    self . id = data [ 'domain_record' ] [ 'id' ]


signature:
def destroy ( self ) :
    """Destroy the record"""

implementation: return self . get_data ( "domains/%s/records/%s" % ( self . domain , self . id ) , type = DELETE , )


signature:
def save ( self ) :
    """Save existing record"""

implementation:
data = { "type" : self . type , "data" : self . data , "name" : self . name , "priority" : self . priority , "port" : self . port , "ttl" : self . ttl , "weight" : self . weight , "flags" : self . flags , "tags" : self . tags }
return self . get_data ( "domains/%s/records/%s" % ( self . domain , self . id ) , type = PUT , params = data )


signature:
def __perform_request ( self , url , type = GET , params = None ) :
    """This method will perform the real request ,
 in this way we can customize only the " output " of the API call by
 using self . _ _ call _ api method .
 This method will return the request object ."""

implementation:
if params is None :
    params = { }
if not self . token :
    raise TokenError ( "No token provided. Please use a valid token" )
url = urlparse . urljoin ( self . end_point , url )
# lookup table to find out the appropriate requests method ,
# headers and payload type ( json or query parameters )
identity = lambda x : x
json_dumps = lambda x : json . dumps ( x )
lookup = { GET : ( self . _session . get , { } , 'params' , identity ) , POST : ( self . _session . post , { 'Content-type' : 'application/json' } , 'data' , json_dumps ) , PUT : ( self . _session . put , { 'Content-type' : 'application/json' } , 'data' , json_dumps ) , DELETE : ( self . _session . delete , { 'content-type' : 'application/json' } , 'data' , json_dumps ) , }
requests_method , headers , payload , transform = lookup [ type ]
agent = "{0}/{1} {2}/{3}" . format ( 'python-digitalocean' , __version__ , requests . __name__ , requests . __version__ )
headers . update ( { 'Authorization' : 'Bearer ' + self . token , 'User-Agent' : agent } )
kwargs = { 'headers' : headers , payload : transform ( params ) }
timeout = self . get_timeout ( )
if timeout :
    kwargs [ 'timeout' ] = timeout
# remove token from log
headers_str = str ( headers ) . replace ( self . token . strip ( ) , 'TOKEN' )
self . _log . debug ( '%s %s %s:%s %s %s' % ( type , url , payload , params , headers_str , timeout ) )
return requests_method ( url , ** kwargs )


signature:
def __deal_with_pagination ( self , url , method , params , data ) :
    """Perform multiple calls in order to have a full list of elements
 when the API are " paginated " . ( content list is divided in more
 than one page )"""

implementation:
all_data = data
while data . get ( "links" , { } ) . get ( "pages" , { } ) . get ( "next" ) :
    url , query = data [ "links" ] [ "pages" ] [ "next" ] . split ( "?" , 1 )
    # Merge the query parameters
    for key , value in urlparse . parse_qs ( query ) . items ( ) :
        params [ key ] = value
    data = self . __perform_request ( url , method , params ) . json ( )
    # Merge the dictionaries
    for key , value in data . items ( ) :
        if isinstance ( value , list ) and key in all_data :
            all_data [ key ] += value
        else :
            all_data [ key ] = value
return all_data


signature:
def get_timeout ( self ) :
    """Checks if any timeout for the requests to DigitalOcean is required .
 To set a timeout , use the REQUEST _ TIMEOUT _ ENV _ VAR environment
 variable ."""

implementation:
timeout_str = os . environ . get ( REQUEST_TIMEOUT_ENV_VAR )
if timeout_str :
    try :
        return float ( timeout_str )
    except :
        self . _log . error ( 'Failed parsing the request read timeout of ' '"%s". Please use a valid float number!' % timeout_str )
return None


signature:
def get_data ( self , url , type = GET , params = None ) :
    """This method is a basic implementation of _ _ call _ api that checks
 errors too . In case of success the method will return True or the
 content of the response to the request .
 Pagination is automatically detected and handled accordingly"""

implementation:
if params is None :
    params = dict ( )
# If per _ page is not set , make sure it has a sane default
if type is GET :
    params . setdefault ( "per_page" , 200 )
req = self . __perform_request ( url , type , params )
if req . status_code == 204 :
    return True
if req . status_code == 404 :
    raise NotFoundError ( )
try :
    data = req . json ( )
except ValueError as e :
    raise JSONReadError ( 'Read failed from DigitalOcean: %s' % str ( e ) )
if not req . ok :
    msg = [ data [ m ] for m in ( "id" , "message" ) if m in data ] [ 1 ]
    raise DataReadError ( msg )
# init request limits
self . __init_ratelimit ( req . headers )
# If there are more elements available ( total ) than the elements per
# page , try to deal with pagination . Note : Breaking the logic on
# multiple pages ,
pages = data . get ( "links" , { } ) . get ( "pages" , { } )
if pages . get ( "next" ) and "page" not in params :
    return self . __deal_with_pagination ( url , type , params , data )
else :
    return data


signature:
def get_object ( cls , api_token , volume_id ) :
    """Class method that will return an Volume object by ID ."""

implementation:
volume = cls ( token = api_token , id = volume_id )
volume . load ( )
return volume


signature:
def create_from_snapshot ( self , * args , ** kwargs ) :
    """Creates a Block Storage volume
 Note : Every argument and parameter given to this method will be
 assigned to the object .
 Args :
 name : string - a name for the volume
 snapshot _ id : string - unique identifier for the volume snapshot
 size _ gigabytes : int - size of the Block Storage volume in GiB
 filesystem _ type : string , optional - name of the filesystem type the
 volume will be formated with ( ' ext4 ' or ' xfs ' )
 filesystem _ label : string , optional - the label to be applied to the
 filesystem , only used in conjunction with filesystem _ type
 Optional Args :
 description : string - text field to describe a volume"""

implementation:
data = self . get_data ( 'volumes/' , type = POST , params = { 'name' : self . name , 'snapshot_id' : self . snapshot_id , 'region' : self . region , 'size_gigabytes' : self . size_gigabytes , 'description' : self . description , 'filesystem_type' : self . filesystem_type , 'filesystem_label' : self . filesystem_label } )
if data :
    self . id = data [ 'volume' ] [ 'id' ]
    self . created_at = data [ 'volume' ] [ 'created_at' ]
return self


signature:
def attach ( self , droplet_id , region ) :
    """Attach a Volume to a Droplet .
 Args :
 droplet _ id : int - droplet id
 region : string - slug identifier for the region"""

implementation: return self . get_data ( "volumes/%s/actions/" % self . id , type = POST , params = { "type" : "attach" , "droplet_id" : droplet_id , "region" : region } )


signature:
def resize ( self , size_gigabytes , region ) :
    """Detach a Volume to a Droplet .
 Args :
 size _ gigabytes : int - size of the Block Storage volume in GiB
 region : string - slug identifier for the region"""

implementation: return self . get_data ( "volumes/%s/actions/" % self . id , type = POST , params = { "type" : "resize" , "size_gigabytes" : size_gigabytes , "region" : region } )


signature:
def snapshot ( self , name ) :
    """Create a snapshot of the volume .
 Args :
 name : string - a human - readable name for the snapshot"""

implementation: return self . get_data ( "volumes/%s/snapshots/" % self . id , type = POST , params = { "name" : name } )


signature:
def get_snapshots ( self ) :
    """Retrieve the list of snapshots that have been created from a volume .
 Args :"""

implementation:
data = self . get_data ( "volumes/%s/snapshots/" % self . id )
snapshots = list ( )
for jsond in data [ u'snapshots' ] :
    snapshot = Snapshot ( ** jsond )
    snapshot . token = self . token
    snapshots . append ( snapshot )
return snapshots


signature:
def get_object ( cls , api_token , cert_id ) :
    """Class method that will return a Certificate object by its ID ."""

implementation:
certificate = cls ( token = api_token , id = cert_id )
certificate . load ( )
return certificate


signature:
def load ( self ) :
    """Load the Certificate object from DigitalOcean .
 Requires self . id to be set ."""

implementation:
data = self . get_data ( "certificates/%s" % self . id )
certificate = data [ "certificate" ]
for attr in certificate . keys ( ) :
    setattr ( self , attr , certificate [ attr ] )
return self


signature:
def create ( self ) :
    """Create the Certificate"""

implementation:
params = { "name" : self . name , "type" : self . type , "dns_names" : self . dns_names , "private_key" : self . private_key , "leaf_certificate" : self . leaf_certificate , "certificate_chain" : self . certificate_chain }
data = self . get_data ( "certificates/" , type = POST , params = params )
if data :
    self . id = data [ 'certificate' ] [ 'id' ]
    self . not_after = data [ 'certificate' ] [ 'not_after' ]
    self . sha1_fingerprint = data [ 'certificate' ] [ 'sha1_fingerprint' ]
    self . created_at = data [ 'certificate' ] [ 'created_at' ]
    self . type = data [ 'certificate' ] [ 'type' ]
    self . dns_names = data [ 'certificate' ] [ 'dns_names' ]
    self . state = data [ 'certificate' ] [ 'state' ]
return self


signature:
def get_object ( cls , api_token , image_id_or_slug ) :
    """Class method that will return an Image object by ID or slug .
 This method is used to validate the type of the image . If it is a
 number , it will be considered as an Image ID , instead if it is a
 string , it will considered as slug ."""

implementation:
if cls . _is_string ( image_id_or_slug ) :
    image = cls ( token = api_token , slug = image_id_or_slug )
    image . load ( use_slug = True )
else :
    image = cls ( token = api_token , id = image_id_or_slug )
    image . load ( )
return image


signature:
def _is_string ( value ) :
    """Checks if the value provided is a string ( True ) or not integer
 ( False ) or something else ( None ) ."""

implementation:
if type ( value ) in [ type ( u'' ) , type ( '' ) ] :
    return True
elif type ( value ) in [ int , type ( 2 ** 64 ) ] :
    return False
else :
    return None


signature:
def create ( self ) :
    """Creates a new custom DigitalOcean Image from the Linux virtual machine
 image located at the provided ` url ` ."""

implementation:
params = { 'name' : self . name , 'region' : self . region , 'url' : self . url , 'distribution' : self . distribution , 'description' : self . description , 'tags' : self . tags }
data = self . get_data ( 'images' , type = POST , params = params )
if data :
    for attr in data [ 'image' ] . keys ( ) :
        setattr ( self , attr , data [ 'image' ] [ attr ] )
return self


signature:
def load ( self , use_slug = False ) :
    """Load slug .
 Loads by id , or by slug if id is not present or use slug is True ."""

implementation:
identifier = None
if use_slug or not self . id :
    identifier = self . slug
else :
    identifier = self . id
if not identifier :
    raise NotFoundError ( "One of self.id or self.slug must be set." )
data = self . get_data ( "images/%s" % identifier )
image_dict = data [ 'image' ]
# Setting the attribute values
for attr in image_dict . keys ( ) :
    setattr ( self , attr , image_dict [ attr ] )
return self


signature:
def transfer ( self , new_region_slug ) :
    """Transfer the image"""

implementation: return self . get_data ( "images/%s/actions/" % self . id , type = POST , params = { "type" : "transfer" , "region" : new_region_slug } )


signature:
def rename ( self , new_name ) :
    """Rename an image"""

implementation: return self . get_data ( "images/%s" % self . id , type = PUT , params = { "name" : new_name } )


signature:
def convert_conv ( params , w_name , scope_name , inputs , layers , weights , names ) :
    """Convert convolution layer .
 Args :
 params : dictionary with layer parameters
 w _ name : name prefix in state _ dict
 scope _ name : pytorch scope name
 inputs : pytorch node inputs
 layers : dictionary with keras tensors
 weights : pytorch state _ dict
 names : use short names for keras layers"""

implementation:
print ( 'Converting convolution ...' )
if names == 'short' :
    tf_name = 'C' + random_string ( 7 )
elif names == 'keep' :
    tf_name = w_name
else :
    tf_name = w_name + str ( random . random ( ) )
bias_name = '{0}.bias' . format ( w_name )
weights_name = '{0}.weight' . format ( w_name )
input_name = inputs [ 0 ]
if len ( weights [ weights_name ] . numpy ( ) . shape ) == 5 : # 3D conv
    W = weights [ weights_name ] . numpy ( ) . transpose ( 2 , 3 , 4 , 1 , 0 )
    height , width , channels , n_layers , n_filters = W . shape
    if bias_name in weights :
        biases = weights [ bias_name ] . numpy ( )
        has_bias = True
    else :
        biases = None
        has_bias = False
    if params [ 'pads' ] [ 0 ] > 0 or params [ 'pads' ] [ 1 ] > 0 :
        padding_name = tf_name + '_pad'
        padding_layer = keras . layers . ZeroPadding3D ( padding = ( params [ 'pads' ] [ 0 ] , params [ 'pads' ] [ 1 ] , params [ 'pads' ] [ 2 ] ) , name = padding_name )
        layers [ padding_name ] = padding_layer ( layers [ input_name ] )
        input_name = padding_name
    if has_bias :
        weights = [ W , biases ]
    else :
        weights = [ W ]
    conv = keras . layers . Conv3D ( filters = n_filters , kernel_size = ( channels , height , width ) , strides = ( params [ 'strides' ] [ 0 ] , params [ 'strides' ] [ 1 ] , params [ 'strides' ] [ 2 ] ) , padding = 'valid' , weights = weights , use_bias = has_bias , activation = None , dilation_rate = params [ 'dilations' ] [ 0 ] , bias_initializer = 'zeros' , kernel_initializer = 'zeros' , name = tf_name )
    layers [ scope_name ] = conv ( layers [ input_name ] )
elif len ( weights [ weights_name ] . numpy ( ) . shape ) == 4 : # 2D conv
    if params [ 'pads' ] [ 0 ] > 0 or params [ 'pads' ] [ 1 ] > 0 :
        padding_name = tf_name + '_pad'
        padding_layer = keras . layers . ZeroPadding2D ( padding = ( params [ 'pads' ] [ 0 ] , params [ 'pads' ] [ 1 ] ) , name = padding_name )
        layers [ padding_name ] = padding_layer ( layers [ input_name ] )
        input_name = padding_name
    W = weights [ weights_name ] . numpy ( ) . transpose ( 2 , 3 , 1 , 0 )
    height , width , channels_per_group , out_channels = W . shape
    n_groups = params [ 'group' ]
    in_channels = channels_per_group * n_groups
    if n_groups == in_channels and n_groups != 1 :
        if bias_name in weights :
            biases = weights [ bias_name ] . numpy ( )
            has_bias = True
        else :
            biases = None
            has_bias = False
        W = W . transpose ( 0 , 1 , 3 , 2 )
        if has_bias :
            weights = [ W , biases ]
        else :
            weights = [ W ]
        conv = keras . layers . DepthwiseConv2D ( kernel_size = ( height , width ) , strides = ( params [ 'strides' ] [ 0 ] , params [ 'strides' ] [ 1 ] ) , padding = 'valid' , use_bias = has_bias , activation = None , depth_multiplier = 1 , weights = weights , dilation_rate = params [ 'dilations' ] [ 0 ] , bias_initializer = 'zeros' , kernel_initializer = 'zeros' )
        layers [ scope_name ] = conv ( layers [ input_name ] )
    elif n_groups != 1 : # Example from https : / / kratzert . github . io / 2017/02/24 / finetuning - alexnet - with - tensorflow . html
    # # Split input and weights and convolve them separately
    # input _ groups = tf . split ( axis = 3 , num _ or _ size _ splits = groups , value = x )
    # weight _ groups = tf . split ( axis = 3 , num _ or _ size _ splits = groups , value = weights )
    # output _ groups = [ convolve ( i , k ) for i , k in zip ( input _ groups , weight _ groups ) ]
    # # Concat the convolved output together again
    # conv = tf . concat ( axis = 3 , values = output _ groups )
        def target_layer ( x , groups = params [ 'group' ] , stride_y = params [ 'strides' ] [ 0 ] , stride_x = params [ 'strides' ] [ 1 ] ) :
            x = tf . transpose ( x , [ 0 , 2 , 3 , 1 ] )
            def convolve_lambda ( i , k ) :
                return tf . nn . conv2d ( i , k , strides = [ 1 , stride_y , stride_x , 1 ] , padding = 'VALID' )
            input_groups = tf . split ( axis = 3 , num_or_size_splits = groups , value = x )
            weight_groups = tf . split ( axis = 3 , num_or_size_splits = groups , value = W . transpose ( 0 , 1 , 2 , 3 ) )
            output_groups = [ convolve_lambda ( i , k ) for i , k in zip ( input_groups , weight_groups ) ]
            layer = tf . concat ( axis = 3 , values = output_groups )
            layer = tf . transpose ( layer , [ 0 , 3 , 1 , 2 ] )
            return layer
        lambda_layer = keras . layers . Lambda ( target_layer )
        layers [ scope_name ] = lambda_layer ( layers [ input_name ] )
    else :
        if bias_name in weights :
            biases = weights [ bias_name ] . numpy ( )
            has_bias = True
        else :
            biases = None
            has_bias = False
        if has_bias :
            weights = [ W , biases ]
        else :
            weights = [ W ]
        conv = keras . layers . Conv2D ( filters = out_channels , kernel_size = ( height , width ) , strides = ( params [ 'strides' ] [ 0 ] , params [ 'strides' ] [ 1 ] ) , padding = 'valid' , weights = weights , use_bias = has_bias , activation = None , dilation_rate = params [ 'dilations' ] [ 0 ] , bias_initializer = 'zeros' , kernel_initializer = 'zeros' , name = tf_name )
        layers [ scope_name ] = conv ( layers [ input_name ] )
else : # 1D conv
    W = weights [ weights_name ] . numpy ( ) . transpose ( 2 , 1 , 0 )
    width , channels , n_filters = W . shape
    n_groups = params [ 'group' ]
    if n_groups > 1 :
        raise AssertionError ( 'Cannot convert conv1d with groups != 1' )
    if bias_name in weights :
        biases = weights [ bias_name ] . numpy ( )
        has_bias = True
    else :
        biases = None
        has_bias = False
    padding_name = tf_name + '_pad'
    padding_layer = keras . layers . ZeroPadding1D ( padding = params [ 'pads' ] [ 0 ] , name = padding_name )
    layers [ padding_name ] = padding_layer ( layers [ inputs [ 0 ] ] )
    input_name = padding_name
    if has_bias :
        weights = [ W , biases ]
    else :
        weights = [ W ]
    conv = keras . layers . Conv1D ( filters = channels , kernel_size = width , strides = params [ 'strides' ] , padding = 'valid' , weights = weights , use_bias = has_bias , activation = None , data_format = 'channels_first' , dilation_rate = params [ 'dilations' ] , bias_initializer = 'zeros' , kernel_initializer = 'zeros' , name = tf_name )
    layers [ scope_name ] = conv ( layers [ input_name ] )


signature:
def convert_convtranspose ( params , w_name , scope_name , inputs , layers , weights , names ) :
    """Convert transposed convolution layer .
 Args :
 params : dictionary with layer parameters
 w _ name : name prefix in state _ dict
 scope _ name : pytorch scope name
 inputs : pytorch node inputs
 layers : dictionary with keras tensors
 weights : pytorch state _ dict
 names : use short names for keras layers"""

implementation:
print ( 'Converting transposed convolution ...' )
if names == 'short' :
    tf_name = 'C' + random_string ( 7 )
elif names == 'keep' :
    tf_name = w_name
else :
    tf_name = w_name + str ( random . random ( ) )
bias_name = '{0}.bias' . format ( w_name )
weights_name = '{0}.weight' . format ( w_name )
if len ( weights [ weights_name ] . numpy ( ) . shape ) == 4 :
    W = weights [ weights_name ] . numpy ( ) . transpose ( 2 , 3 , 1 , 0 )
    height , width , n_filters , channels = W . shape
    n_groups = params [ 'group' ]
    if n_groups > 1 :
        raise AssertionError ( 'Cannot convert conv1d with groups != 1' )
    if params [ 'dilations' ] [ 0 ] > 1 :
        raise AssertionError ( 'Cannot convert conv1d with dilation_rate != 1' )
    if bias_name in weights :
        biases = weights [ bias_name ] . numpy ( )
        has_bias = True
    else :
        biases = None
        has_bias = False
    input_name = inputs [ 0 ]
    if has_bias :
        weights = [ W , biases ]
    else :
        weights = [ W ]
    conv = keras . layers . Conv2DTranspose ( filters = n_filters , kernel_size = ( height , width ) , strides = ( params [ 'strides' ] [ 0 ] , params [ 'strides' ] [ 1 ] ) , padding = 'valid' , output_padding = 0 , weights = weights , use_bias = has_bias , activation = None , dilation_rate = params [ 'dilations' ] [ 0 ] , bias_initializer = 'zeros' , kernel_initializer = 'zeros' , name = tf_name )
    layers [ scope_name ] = conv ( layers [ input_name ] )
    # Magic ad - hoc .
    # See the Keras issue : https : / / github . com / keras - team / keras / issues / 6777
    layers [ scope_name ] . set_shape ( layers [ scope_name ] . _keras_shape )
    pads = params [ 'pads' ]
    if pads [ 0 ] > 0 :
        assert ( len ( pads ) == 2 or ( pads [ 2 ] == pads [ 0 ] and pads [ 3 ] == pads [ 1 ] ) )
        crop = keras . layers . Cropping2D ( pads [ : 2 ] , name = tf_name + '_crop' )
        layers [ scope_name ] = crop ( layers [ scope_name ] )
else :
    raise AssertionError ( 'Layer is not supported for now' )


signature:
def convert_sum ( params , w_name , scope_name , inputs , layers , weights , names ) :
    """Convert sum .
 Args :
 params : dictionary with layer parameters
 w _ name : name prefix in state _ dict
 scope _ name : pytorch scope name
 inputs : pytorch node inputs
 layers : dictionary with keras tensors
 weights : pytorch state _ dict
 names : use short names for keras layers"""

implementation:
print ( 'Converting Sum ...' )
def target_layer ( x ) :
    import keras . backend as K
    return K . sum ( x )
lambda_layer = keras . layers . Lambda ( target_layer )
layers [ scope_name ] = lambda_layer ( layers [ inputs [ 0 ] ] )


signature:
def convert_reduce_sum ( params , w_name , scope_name , inputs , layers , weights , names ) :
    """Convert reduce _ sum layer .
 Args :
 params : dictionary with layer parameters
 w _ name : name prefix in state _ dict
 scope _ name : pytorch scope name
 inputs : pytorch node inputs
 layers : dictionary with keras tensors
 weights : pytorch state _ dict
 names : use short names for keras layers"""

implementation:
print ( 'Converting reduce_sum ...' )
keepdims = params [ 'keepdims' ] > 0
axis = params [ 'axes' ]
def target_layer ( x , keepdims = keepdims , axis = axis ) :
    import keras . backend as K
    return K . sum ( x , keepdims = keepdims , axis = axis )
lambda_layer = keras . layers . Lambda ( target_layer )
layers [ scope_name ] = lambda_layer ( layers [ inputs [ 0 ] ] )


signature:
def convert_concat ( params , w_name , scope_name , inputs , layers , weights , names ) :
    """Convert concatenation .
 Args :
 params : dictionary with layer parameters
 w _ name : name prefix in state _ dict
 scope _ name : pytorch scope name
 inputs : pytorch node inputs
 layers : dictionary with keras tensors
 weights : pytorch state _ dict
 names : use short names for keras layers"""

implementation:
print ( 'Converting concat ...' )
concat_nodes = [ layers [ i ] for i in inputs ]
if len ( concat_nodes ) == 1 : # no - op
    layers [ scope_name ] = concat_nodes [ 0 ]
    return
if names == 'short' :
    tf_name = 'CAT' + random_string ( 5 )
elif names == 'keep' :
    tf_name = w_name
else :
    tf_name = w_name + str ( random . random ( ) )
cat = keras . layers . Concatenate ( name = tf_name , axis = params [ 'axis' ] )
layers [ scope_name ] = cat ( concat_nodes )


signature:
def convert_slice ( params , w_name , scope_name , inputs , layers , weights , names ) :
    """Convert slice operation .
 Args :
 params : dictionary with layer parameters
 w _ name : name prefix in state _ dict
 scope _ name : pytorch scope name
 inputs : pytorch node inputs
 layers : dictionary with keras tensors
 weights : pytorch state _ dict
 names : use short names for keras layers"""

implementation:
print ( 'Converting slice ...' )
if len ( params [ 'axes' ] ) > 1 :
    raise AssertionError ( 'Cannot convert slice by multiple dimensions' )
if params [ 'axes' ] [ 0 ] not in [ 0 , 1 , 2 , 3 ] :
    raise AssertionError ( 'Slice by dimension more than 3 or less than 0 is not supported' )
def target_layer ( x , axis = int ( params [ 'axes' ] [ 0 ] ) , start = int ( params [ 'starts' ] [ 0 ] ) , end = int ( params [ 'ends' ] [ 0 ] ) ) :
    if axis == 0 :
        return x [ start : end ]
    elif axis == 1 :
        return x [ : , start : end ]
    elif axis == 2 :
        return x [ : , : , start : end ]
    elif axis == 3 :
        return x [ : , : , : , start : end ]
lambda_layer = keras . layers . Lambda ( target_layer )
layers [ scope_name ] = lambda_layer ( layers [ inputs [ 0 ] ] )


signature:
def convert_clip ( params , w_name , scope_name , inputs , layers , weights , names ) :
    """Convert clip operation .
 Args :
 params : dictionary with layer parameters
 w _ name : name prefix in state _ dict
 scope _ name : pytorch scope name
 inputs : pytorch node inputs
 layers : dictionary with keras tensors
 weights : pytorch state _ dict
 names : use short names for keras layers"""

implementation:
print ( 'Converting clip ...' )
if params [ 'min' ] == 0 :
    print ( "using ReLU({0})" . format ( params [ 'max' ] ) )
    layer = keras . layers . ReLU ( max_value = params [ 'max' ] )
else :
    def target_layer ( x , vmin = params [ 'min' ] , vmax = params [ 'max' ] ) :
        import tensorflow as tf
        return tf . clip_by_value ( x , vmin , vmax )
    layer = keras . layers . Lambda ( target_layer )
layers [ scope_name ] = layer ( layers [ inputs [ 0 ] ] )


signature:
def convert_elementwise_add ( params , w_name , scope_name , inputs , layers , weights , names ) :
    """Convert elementwise addition .
 Args :
 params : dictionary with layer parameters
 w _ name : name prefix in state _ dict
 scope _ name : pytorch scope name
 inputs : pytorch node inputs
 layers : dictionary with keras tensors
 weights : pytorch state _ dict
 names : use short names for keras layers"""

implementation:
print ( 'Converting elementwise_add ...' )
if 'broadcast' in params :
    model0 = layers [ inputs [ 0 ] ]
    model1 = layers [ inputs [ 1 ] ]
    if names == 'short' :
        tf_name = 'A' + random_string ( 7 )
    elif names == 'keep' :
        tf_name = w_name
    else :
        tf_name = w_name + str ( random . random ( ) )
    def target_layer ( x ) :
        layer = tf . add ( x [ 0 ] , x [ 1 ] )
        return layer
    lambda_layer = keras . layers . Lambda ( target_layer , name = tf_name )
    layers [ scope_name ] = lambda_layer ( [ layers [ inputs [ 0 ] ] , layers [ inputs [ 1 ] ] ] )
else :
    model0 = layers [ inputs [ 0 ] ]
    model1 = layers [ inputs [ 1 ] ]
    if names == 'short' :
        tf_name = 'A' + random_string ( 7 )
    elif names == 'keep' :
        tf_name = w_name
    else :
        tf_name = w_name + str ( random . random ( ) )
    add = keras . layers . Add ( name = tf_name )
    layers [ scope_name ] = add ( [ model0 , model1 ] )


signature:
def convert_elementwise_mul ( params , w_name , scope_name , inputs , layers , weights , names ) :
    """Convert elementwise multiplication .
 Args :
 params : dictionary with layer parameters
 w _ name : name prefix in state _ dict
 scope _ name : pytorch scope name
 inputs : pytorch node inputs
 layers : dictionary with keras tensors
 weights : pytorch state _ dict
 names : use short names for keras layers"""

implementation:
print ( 'Converting elementwise_mul ...' )
model0 = layers [ inputs [ 0 ] ]
model1 = layers [ inputs [ 1 ] ]
if names == 'short' :
    tf_name = 'M' + random_string ( 7 )
elif names == 'keep' :
    tf_name = w_name
else :
    tf_name = w_name + str ( random . random ( ) )
def target_layer ( x ) :
    layer = tf . multiply ( x [ 0 ] , x [ 1 ] )
    return layer
lambda_layer = keras . layers . Lambda ( target_layer , name = tf_name )
layers [ scope_name ] = lambda_layer ( [ layers [ inputs [ 0 ] ] , layers [ inputs [ 1 ] ] ] )


signature:
def convert_elementwise_div ( params , w_name , scope_name , inputs , layers , weights , names ) :
    """Convert elementwise multiplication .
 Args :
 params : dictionary with layer parameters
 w _ name : name prefix in state _ dict
 scope _ name : pytorch scope name
 inputs : pytorch node inputs
 layers : dictionary with keras tensors
 weights : pytorch state _ dict
 names : use short names for keras layers"""

implementation:
print ( 'Converting elementwise_div ...' )
if names == 'short' :
    tf_name = 'D' + random_string ( 7 )
elif names == 'keep' :
    tf_name = w_name
else :
    tf_name = w_name + str ( random . random ( ) )
def target_layer ( x ) :
    layer = tf . div ( x [ 0 ] , x [ 1 ] )
    return layer
lambda_layer = keras . layers . Lambda ( target_layer , name = tf_name )
layers [ scope_name ] = lambda_layer ( [ layers [ inputs [ 0 ] ] , layers [ inputs [ 1 ] ] ] )


signature:
def convert_elementwise_sub ( params , w_name , scope_name , inputs , layers , weights , names ) :
    """Convert elementwise subtraction .
 Args :
 params : dictionary with layer parameters
 w _ name : name prefix in state _ dict
 scope _ name : pytorch scope name
 inputs : pytorch node inputs
 layers : dictionary with keras tensors
 weights : pytorch state _ dict
 names : use short names for keras layers"""

implementation:
print ( 'Converting elementwise_sub ...' )
model0 = layers [ inputs [ 0 ] ]
model1 = layers [ inputs [ 1 ] ]
if names == 'short' :
    tf_name = 'S' + random_string ( 7 )
elif names == 'keep' :
    tf_name = w_name
else :
    tf_name = w_name + str ( random . random ( ) )
sub = keras . layers . Subtract ( name = tf_name )
layers [ scope_name ] = sub ( [ model0 , model1 ] )


signature:
def convert_gemm ( params , w_name , scope_name , inputs , layers , weights , names ) :
    """Convert Linear .
 Args :
 params : dictionary with layer parameters
 w _ name : name prefix in state _ dict
 scope _ name : pytorch scope name
 inputs : pytorch node inputs
 layers : dictionary with keras tensors
 weights : pytorch state _ dict
 names : use short names for keras layers"""

implementation:
print ( 'Converting Linear ...' )
if names == 'short' :
    tf_name = 'FC' + random_string ( 6 )
elif names == 'keep' :
    tf_name = w_name
else :
    tf_name = w_name + str ( random . random ( ) )
bias_name = '{0}.bias' . format ( w_name )
weights_name = '{0}.weight' . format ( w_name )
W = weights [ weights_name ] . numpy ( ) . transpose ( )
input_channels , output_channels = W . shape
keras_weights = [ W ]
has_bias = False
if bias_name in weights :
    bias = weights [ bias_name ] . numpy ( )
    keras_weights = [ W , bias ]
    has_bias = True
dense = keras . layers . Dense ( output_channels , weights = keras_weights , use_bias = has_bias , name = tf_name , bias_initializer = 'zeros' , kernel_initializer = 'zeros' , )
layers [ scope_name ] = dense ( layers [ inputs [ 0 ] ] )


signature:
def convert_matmul ( params , w_name , scope_name , inputs , layers , weights , names ) :
    """Convert matmul layer .
 Args :
 params : dictionary with layer parameters
 w _ name : name prefix in state _ dict
 scope _ name : pytorch scope name
 inputs : pytorch node inputs
 layers : dictionary with keras tensors
 weights : pytorch state _ dict
 names : use short names for keras layers"""

implementation:
print ( 'Converting matmul ...' )
if names == 'short' :
    tf_name = 'MMUL' + random_string ( 4 )
elif names == 'keep' :
    tf_name = w_name
else :
    tf_name = w_name + str ( random . random ( ) )
if len ( inputs ) == 1 :
    weights_name = '{0}.weight' . format ( w_name )
    W = weights [ weights_name ] . numpy ( ) . transpose ( )
    input_channels , output_channels = W . shape
    keras_weights = [ W ]
    dense = keras . layers . Dense ( output_channels , weights = keras_weights , use_bias = False , name = tf_name , bias_initializer = 'zeros' , kernel_initializer = 'zeros' , )
    layers [ scope_name ] = dense ( layers [ inputs [ 0 ] ] )
elif len ( inputs ) == 2 :
    weights_name = '{0}.weight' . format ( w_name )
    W = weights [ weights_name ] . numpy ( ) . transpose ( )
    input_channels , output_channels = W . shape
    keras_weights = [ W ]
    dense = keras . layers . Dense ( output_channels , weights = keras_weights , use_bias = False , name = tf_name , bias_initializer = 'zeros' , kernel_initializer = 'zeros' , )
    layers [ scope_name ] = dense ( layers [ inputs [ 0 ] ] )
else :
    raise AssertionError ( 'Cannot convert matmul layer' )


signature:
def convert_constant ( params , w_name , scope_name , inputs , layers , weights , names ) :
    """Convert constant layer .
 Args :
 params : dictionary with layer parameters
 w _ name : name prefix in state _ dict
 scope _ name : pytorch scope name
 inputs : pytorch node inputs
 layers : dictionary with keras tensors
 weights : pytorch state _ dict
 names : use short names for keras layers"""

implementation:
print ( 'Converting constant ...' )
params_list = params [ 'value' ] . numpy ( )
def target_layer ( x , value = params_list ) :
    return tf . constant ( value . tolist ( ) , shape = value . shape )
lambda_layer = keras . layers . Lambda ( target_layer )
layers [ scope_name + '_np' ] = params_list
# ad - hoc
layers [ scope_name ] = lambda_layer ( layers [ list ( layers . keys ( ) ) [ 0 ] ] )


signature:
def convert_flatten ( params , w_name , scope_name , inputs , layers , weights , names ) :
    """Convert reshape ( view ) .
 Args :
 params : dictionary with layer parameters
 w _ name : name prefix in state _ dict
 scope _ name : pytorch scope name
 inputs : pytorch node inputs
 layers : dictionary with keras tensors
 weights : pytorch state _ dict
 names : use short names for keras layers"""

implementation:
print ( 'Converting flatten ...' )
if names == 'short' :
    tf_name = 'R' + random_string ( 7 )
elif names == 'keep' :
    tf_name = w_name
else :
    tf_name = w_name + str ( random . random ( ) )
reshape = keras . layers . Reshape ( [ - 1 ] , name = tf_name )
layers [ scope_name ] = reshape ( layers [ inputs [ 0 ] ] )


signature:
def convert_transpose ( params , w_name , scope_name , inputs , layers , weights , names ) :
    """Convert transpose layer .
 Args :
 params : dictionary with layer parameters
 w _ name : name prefix in state _ dict
 scope _ name : pytorch scope name
 inputs : pytorch node inputs
 layers : dictionary with keras tensors
 weights : pytorch state _ dict
 names : use short names for keras layers"""

implementation:
print ( 'Converting transpose ...' )
if params [ 'perm' ] [ 0 ] != 0 :
    if inputs [ 0 ] in layers :
        print ( '!!! Cannot permute batch dimension. Result may be wrong !!!' )
        layers [ scope_name ] = layers [ inputs [ 0 ] ]
    else :
        print ( 'Skip weight matrix transpose, result may be wrong.' )
else :
    if names :
        tf_name = 'PERM' + random_string ( 4 )
    else :
        tf_name = w_name + str ( random . random ( ) )
    permute = keras . layers . Permute ( params [ 'perm' ] [ 1 : ] , name = tf_name )
    layers [ scope_name ] = permute ( layers [ inputs [ 0 ] ] )


signature:
def convert_reshape ( params , w_name , scope_name , inputs , layers , weights , names ) :
    """Convert reshape layer .
 Args :
 params : dictionary with layer parameters
 w _ name : name prefix in state _ dict
 scope _ name : pytorch scope name
 inputs : pytorch node inputs
 layers : dictionary with keras tensors
 weights : pytorch state _ dict
 names : use short names for keras layers"""

implementation:
print ( 'Converting reshape ...' )
if names == 'short' :
    tf_name = 'RESH' + random_string ( 4 )
elif names == 'keep' :
    tf_name = w_name
else :
    tf_name = w_name + str ( random . random ( ) )
if len ( inputs ) > 1 :
    if layers [ inputs [ 1 ] ] [ 0 ] == - 1 :
        print ( 'Cannot deduct batch size! It will be omitted, but result may be wrong.' )
    reshape = keras . layers . Reshape ( layers [ inputs [ 1 ] + '_np' ] , name = tf_name )
    layers [ scope_name ] = reshape ( layers [ inputs [ 0 ] ] )
else :
    if inputs [ 0 ] in layers :
        reshape = keras . layers . Reshape ( params [ 'shape' ] [ 1 : ] , name = tf_name )
        layers [ scope_name ] = reshape ( layers [ inputs [ 0 ] ] )
    else :
        print ( 'Skip weight matrix transpose, but result may be wrong.' )


signature:
def convert_squeeze ( params , w_name , scope_name , inputs , layers , weights , names ) :
    """Convert squeeze operation .
 Args :
 params : dictionary with layer parameters
 w _ name : name prefix in state _ dict
 scope _ name : pytorch scope name
 inputs : pytorch node inputs
 layers : dictionary with keras tensors
 weights : pytorch state _ dict
 names : use short names for keras layers"""

implementation:
print ( 'Converting squeeze ...' )
if len ( params [ 'axes' ] ) > 1 :
    raise AssertionError ( 'Cannot convert squeeze by multiple dimensions' )
def target_layer ( x , axis = int ( params [ 'axes' ] [ 0 ] ) ) :
    import tensorflow as tf
    return tf . squeeze ( x , axis = axis )
lambda_layer = keras . layers . Lambda ( target_layer )
layers [ scope_name ] = lambda_layer ( layers [ inputs [ 0 ] ] )


signature:
def convert_unsqueeze ( params , w_name , scope_name , inputs , layers , weights , names ) :
    """Convert unsqueeze operation .
 Args :
 params : dictionary with layer parameters
 w _ name : name prefix in state _ dict
 scope _ name : pytorch scope name
 inputs : pytorch node inputs
 layers : dictionary with keras tensors
 weights : pytorch state _ dict
 names : use short names for keras layers"""

implementation:
print ( 'Converting unsqueeze ...' )
if names == 'short' :
    tf_name = 'UNSQ' + random_string ( 4 )
elif names == 'keep' :
    tf_name = w_name
else :
    tf_name = w_name + str ( random . random ( ) )
def target_layer ( x ) :
    import keras
    return keras . backend . expand_dims ( x )
lambda_layer = keras . layers . Lambda ( target_layer , name = tf_name + 'E' )
layers [ scope_name ] = lambda_layer ( layers [ inputs [ 0 ] ] )


signature:
def convert_shape ( params , w_name , scope_name , inputs , layers , weights , names ) :
    """Convert shape operation .
 Args :
 params : dictionary with layer parameters
 w _ name : name prefix in state _ dict
 scope _ name : pytorch scope name
 inputs : pytorch node inputs
 layers : dictionary with keras tensors
 weights : pytorch state _ dict
 names : use short names for keras layers"""

implementation:
print ( 'Converting shape ...' )
def target_layer ( x ) :
    import tensorflow as tf
    return tf . shape ( x )
lambda_layer = keras . layers . Lambda ( target_layer )
layers [ scope_name ] = lambda_layer ( layers [ inputs [ 0 ] ] )


signature:
def convert_avgpool ( params , w_name , scope_name , inputs , layers , weights , names ) :
    """Convert Average pooling .
 Args :
 params : dictionary with layer parameters
 w _ name : name prefix in state _ dict
 scope _ name : pytorch scope name
 inputs : pytorch node inputs
 layers : dictionary with keras tensors
 weights : pytorch state _ dict
 names : use short names for keras layers"""

implementation:
print ( 'Converting pooling ...' )
if names == 'short' :
    tf_name = 'P' + random_string ( 7 )
elif names == 'keep' :
    tf_name = w_name
else :
    tf_name = w_name + str ( random . random ( ) )
if 'kernel_shape' in params :
    height , width = params [ 'kernel_shape' ]
else :
    height , width = params [ 'kernel_size' ]
if 'strides' in params :
    stride_height , stride_width = params [ 'strides' ]
else :
    stride_height , stride_width = params [ 'stride' ]
if 'pads' in params :
    padding_h , padding_w , _ , _ = params [ 'pads' ]
else :
    padding_h , padding_w = params [ 'padding' ]
input_name = inputs [ 0 ]
pad = 'valid'
if height % 2 == 1 and width % 2 == 1 and height // 2 == padding_h and width // 2 == padding_w and stride_height == 1 and stride_width == 1 :
    pad = 'same'
else :
    padding_name = tf_name + '_pad'
    padding_layer = keras . layers . ZeroPadding2D ( padding = ( padding_h , padding_w ) , name = padding_name )
    layers [ padding_name ] = padding_layer ( layers [ inputs [ 0 ] ] )
    input_name = padding_name
# Pooling type AveragePooling2D
pooling = keras . layers . AveragePooling2D ( pool_size = ( height , width ) , strides = ( stride_height , stride_width ) , padding = pad , name = tf_name , data_format = 'channels_first' )
layers [ scope_name ] = pooling ( layers [ input_name ] )


signature:
def convert_maxpool3 ( params , w_name , scope_name , inputs , layers , weights , names ) :
    """Convert 3d Max pooling .
 Args :
 params : dictionary with layer parameters
 w _ name : name prefix in state _ dict
 scope _ name : pytorch scope name
 inputs : pytorch node inputs
 layers : dictionary with keras tensors
 weights : pytorch state _ dict
 names : use short names for keras layers"""

implementation:
print ( 'Converting pooling ...' )
if names == 'short' :
    tf_name = 'P' + random_string ( 7 )
elif names == 'keep' :
    tf_name = w_name
else :
    tf_name = w_name + str ( random . random ( ) )
if 'kernel_shape' in params :
    height , width , depth = params [ 'kernel_shape' ]
else :
    height , width , depth = params [ 'kernel_size' ]
if 'strides' in params :
    stride_height , stride_width , stride_depth = params [ 'strides' ]
else :
    stride_height , stride_width , stride_depth = params [ 'stride' ]
if 'pads' in params :
    padding_h , padding_w , padding_d , _ , _ = params [ 'pads' ]
else :
    padding_h , padding_w , padding_d = params [ 'padding' ]
input_name = inputs [ 0 ]
if padding_h > 0 and padding_w > 0 and padding_d > 0 :
    padding_name = tf_name + '_pad'
    padding_layer = keras . layers . ZeroPadding3D ( padding = ( padding_h , padding_w , padding_d ) , name = padding_name )
    layers [ padding_name ] = padding_layer ( layers [ inputs [ 0 ] ] )
    input_name = padding_name
# Pooling type
pooling = keras . layers . MaxPooling3D ( pool_size = ( height , width , depth ) , strides = ( stride_height , stride_width , stride_depth ) , padding = 'valid' , name = tf_name )
layers [ scope_name ] = pooling ( layers [ input_name ] )


signature:
def convert_adaptive_max_pool2d ( params , w_name , scope_name , inputs , layers , weights , names ) :
    """Convert convert _ adaptive _ max _ pool2d layer .
 Args :
 params : dictionary with layer parameters
 w _ name : name prefix in state _ dict
 scope _ name : pytorch scope name
 inputs : pytorch node inputs
 layers : dictionary with keras tensors
 weights : pytorch state _ dict
 names : use short names for keras layers"""

implementation:
print ( 'Converting adaptive_avg_pool2d...' )
if names == 'short' :
    tf_name = 'APOL' + random_string ( 4 )
elif names == 'keep' :
    tf_name = w_name
else :
    tf_name = w_name + str ( random . random ( ) )
global_pool = keras . layers . GlobalMaxPooling2D ( data_format = 'channels_first' , name = tf_name )
layers [ scope_name ] = global_pool ( layers [ inputs [ 0 ] ] )
def target_layer ( x ) :
    import keras
    return keras . backend . expand_dims ( x )
lambda_layer = keras . layers . Lambda ( target_layer , name = tf_name + 'E' )
layers [ scope_name ] = lambda_layer ( layers [ scope_name ] )
# double expand dims
layers [ scope_name ] = lambda_layer ( layers [ scope_name ] )


signature:
def convert_padding ( params , w_name , scope_name , inputs , layers , weights , names ) :
    """Convert padding layer .
 Args :
 params : dictionary with layer parameters
 w _ name : name prefix in state _ dict
 scope _ name : pytorch scope name
 inputs : pytorch node inputs
 layers : dictionary with keras tensors
 weights : pytorch state _ dict
 names : use short names for keras layers"""

implementation:
print ( 'Converting padding...' )
if params [ 'mode' ] == 'constant' : # raise AssertionError ( ' Cannot convert non - constant padding ' )
    if params [ 'value' ] != 0.0 :
        raise AssertionError ( 'Cannot convert non-zero padding' )
    if names :
        tf_name = 'PADD' + random_string ( 4 )
    else :
        tf_name = w_name + str ( random . random ( ) )
    # Magic ordering
    padding_name = tf_name
    padding_layer = keras . layers . ZeroPadding2D ( padding = ( ( params [ 'pads' ] [ 2 ] , params [ 'pads' ] [ 6 ] ) , ( params [ 'pads' ] [ 3 ] , params [ 'pads' ] [ 7 ] ) ) , name = padding_name )
    layers [ scope_name ] = padding_layer ( layers [ inputs [ 0 ] ] )
elif params [ 'mode' ] == 'reflect' :
    def target_layer ( x , pads = params [ 'pads' ] ) : # x = tf . transpose ( x , [ 0 , 2 , 3 , 1 ] )
        layer = tf . pad ( x , [ [ 0 , 0 ] , [ 0 , 0 ] , [ pads [ 2 ] , pads [ 6 ] ] , [ pads [ 3 ] , pads [ 7 ] ] ] , 'REFLECT' )
        # layer = tf . transpose ( layer , [ 0 , 3 , 1 , 2 ] )
        return layer
    lambda_layer = keras . layers . Lambda ( target_layer )
    layers [ scope_name ] = lambda_layer ( layers [ inputs [ 0 ] ] )


signature:
def convert_batchnorm ( params , w_name , scope_name , inputs , layers , weights , names ) :
    """Convert batch normalization layer .
 Args :
 params : dictionary with layer parameters
 w _ name : name prefix in state _ dict
 scope _ name : pytorch scope name
 inputs : pytorch node inputs
 layers : dictionary with keras tensors
 weights : pytorch state _ dict
 names : use short names for keras layers"""

implementation:
print ( 'Converting batchnorm ...' )
if names == 'short' :
    tf_name = 'BN' + random_string ( 6 )
elif names == 'keep' :
    tf_name = w_name
else :
    tf_name = w_name + str ( random . random ( ) )
bias_name = '{0}.bias' . format ( w_name )
weights_name = '{0}.weight' . format ( w_name )
mean_name = '{0}.running_mean' . format ( w_name )
var_name = '{0}.running_var' . format ( w_name )
if bias_name in weights :
    beta = weights [ bias_name ] . numpy ( )
if weights_name in weights :
    gamma = weights [ weights_name ] . numpy ( )
mean = weights [ mean_name ] . numpy ( )
variance = weights [ var_name ] . numpy ( )
eps = params [ 'epsilon' ]
momentum = params [ 'momentum' ]
if weights_name not in weights :
    bn = keras . layers . BatchNormalization ( axis = 1 , momentum = momentum , epsilon = eps , center = False , scale = False , weights = [ mean , variance ] , name = tf_name )
else :
    bn = keras . layers . BatchNormalization ( axis = 1 , momentum = momentum , epsilon = eps , weights = [ gamma , beta , mean , variance ] , name = tf_name )
layers [ scope_name ] = bn ( layers [ inputs [ 0 ] ] )


signature:
def convert_instancenorm ( params , w_name , scope_name , inputs , layers , weights , names ) :
    """Convert instance normalization layer .
 Args :
 params : dictionary with layer parameters
 w _ name : name prefix in state _ dict
 scope _ name : pytorch scope name
 inputs : pytorch node inputs
 layers : dictionary with keras tensors
 weights : pytorch state _ dict
 names : use short names for keras layers"""

implementation:
print ( 'Converting instancenorm ...' )
if names == 'short' :
    tf_name = 'IN' + random_string ( 6 )
elif names == 'keep' :
    tf_name = w_name
else :
    tf_name = w_name + str ( random . random ( ) )
assert ( len ( inputs ) == 3 )
bias_name = '{0}.bias' . format ( w_name )
weights_name = '{0}.weight' . format ( w_name )
# Use previously taken constants
if inputs [ - 2 ] + '_np' in layers :
    gamma = layers [ inputs [ - 2 ] + '_np' ]
else :
    gamma = weights [ weights_name ] . numpy ( )
if inputs [ - 1 ] + '_np' in layers :
    beta = layers [ inputs [ - 1 ] + '_np' ]
else :
    beta = weights [ bias_name ] . numpy ( )
def target_layer ( x , epsilon = params [ 'epsilon' ] , gamma = gamma , beta = beta ) :
    layer = tf . contrib . layers . instance_norm ( x , param_initializers = { 'beta' : tf . constant_initializer ( beta ) , 'gamma' : tf . constant_initializer ( gamma ) } , epsilon = epsilon , data_format = 'NCHW' , trainable = False )
    return layer
lambda_layer = keras . layers . Lambda ( target_layer , name = tf_name )
layers [ scope_name ] = lambda_layer ( layers [ inputs [ 0 ] ] )


signature:
def convert_dropout ( params , w_name , scope_name , inputs , layers , weights , names ) :
    """Convert dropout .
 Args :
 params : dictionary with layer parameters
 w _ name : name prefix in state _ dict
 scope _ name : pytorch scope name
 inputs : pytorch node inputs
 layers : dictionary with keras tensors
 weights : pytorch state _ dict
 names : use short names for keras layers"""

implementation:
print ( 'Converting dropout ...' )
if names == 'short' :
    tf_name = 'DO' + random_string ( 6 )
elif names == 'keep' :
    tf_name = w_name
else :
    tf_name = w_name + str ( random . random ( ) )
dropout = keras . layers . Dropout ( rate = params [ 'ratio' ] , name = tf_name )
layers [ scope_name ] = dropout ( layers [ inputs [ 0 ] ] )


signature:
def convert_relu ( params , w_name , scope_name , inputs , layers , weights , names ) :
    """Convert relu layer .
 Args :
 params : dictionary with layer parameters
 w _ name : name prefix in state _ dict
 scope _ name : pytorch scope name
 inputs : pytorch node inputs
 layers : dictionary with keras tensors
 weights : pytorch state _ dict
 names : use short names for keras layers"""

implementation:
print ( 'Converting relu ...' )
if names == 'short' :
    tf_name = 'RELU' + random_string ( 4 )
elif names == 'keep' :
    tf_name = w_name
else :
    tf_name = w_name + str ( random . random ( ) )
relu = keras . layers . Activation ( 'relu' , name = tf_name )
layers [ scope_name ] = relu ( layers [ inputs [ 0 ] ] )


signature:
def convert_lrelu ( params , w_name , scope_name , inputs , layers , weights , names ) :
    """Convert leaky relu layer .
 Args :
 params : dictionary with layer parameters
 w _ name : name prefix in state _ dict
 scope _ name : pytorch scope name
 inputs : pytorch node inputs
 layers : dictionary with keras tensors
 weights : pytorch state _ dict
 names : use short names for keras layers"""

implementation:
print ( 'Converting lrelu ...' )
if names == 'short' :
    tf_name = 'lRELU' + random_string ( 3 )
elif names == 'keep' :
    tf_name = w_name
else :
    tf_name = w_name + str ( random . random ( ) )
leakyrelu = keras . layers . LeakyReLU ( alpha = params [ 'alpha' ] , name = tf_name )
layers [ scope_name ] = leakyrelu ( layers [ inputs [ 0 ] ] )


signature:
def convert_sigmoid ( params , w_name , scope_name , inputs , layers , weights , names ) :
    """Convert sigmoid layer .
 Args :
 params : dictionary with layer parameters
 w _ name : name prefix in state _ dict
 scope _ name : pytorch scope name
 inputs : pytorch node inputs
 layers : dictionary with keras tensors
 weights : pytorch state _ dict
 names : use short names for keras layers"""

implementation:
print ( 'Converting sigmoid ...' )
if names == 'short' :
    tf_name = 'SIGM' + random_string ( 4 )
elif names == 'keep' :
    tf_name = w_name
else :
    tf_name = w_name + str ( random . random ( ) )
sigmoid = keras . layers . Activation ( 'sigmoid' , name = tf_name )
layers [ scope_name ] = sigmoid ( layers [ inputs [ 0 ] ] )


signature:
def convert_softmax ( params , w_name , scope_name , inputs , layers , weights , names ) :
    """Convert softmax layer .
 Args :
 params : dictionary with layer parameters
 w _ name : name prefix in state _ dict
 scope _ name : pytorch scope name
 inputs : pytorch node inputs
 layers : dictionary with keras tensors
 weights : pytorch state _ dict
 names : use short names for keras layers"""

implementation:
print ( 'Converting softmax ...' )
if names == 'short' :
    tf_name = 'SMAX' + random_string ( 4 )
elif names == 'keep' :
    tf_name = w_name
else :
    tf_name = w_name + str ( random . random ( ) )
def target_layer ( x , dim = params [ 'dim' ] ) :
    import keras
    return keras . activations . softmax ( x , axis = dim )
lambda_layer = keras . layers . Lambda ( target_layer )
layers [ scope_name ] = lambda_layer ( layers [ inputs [ 0 ] ] )


signature:
def convert_tanh ( params , w_name , scope_name , inputs , layers , weights , names ) :
    """Convert tanh layer .
 Args :
 params : dictionary with layer parameters
 w _ name : name prefix in state _ dict
 scope _ name : pytorch scope name
 inputs : pytorch node inputs
 layers : dictionary with keras tensors
 weights : pytorch state _ dict
 names : use short names for keras layers"""

implementation:
print ( 'Converting tanh ...' )
if names == 'short' :
    tf_name = 'TANH' + random_string ( 4 )
elif names == 'keep' :
    tf_name = w_name
else :
    tf_name = w_name + str ( random . random ( ) )
tanh = keras . layers . Activation ( 'tanh' , name = tf_name )
layers [ scope_name ] = tanh ( layers [ inputs [ 0 ] ] )


signature:
def convert_hardtanh ( params , w_name , scope_name , inputs , layers , weights , names ) :
    """Convert hardtanh layer .
 Args :
 params : dictionary with layer parameters
 w _ name : name prefix in state _ dict
 scope _ name : pytorch scope name
 inputs : pytorch node inputs
 layers : dictionary with keras tensors
 weights : pytorch state _ dict
 names : use short names for keras layers"""

implementation:
print ( 'Converting hardtanh (clip) ...' )
def target_layer ( x , max_val = float ( params [ 'max_val' ] ) , min_val = float ( params [ 'min_val' ] ) ) :
    return tf . minimum ( max_val , tf . maximum ( min_val , x ) )
lambda_layer = keras . layers . Lambda ( target_layer )
layers [ scope_name ] = lambda_layer ( layers [ inputs [ 0 ] ] )


signature:
def convert_selu ( params , w_name , scope_name , inputs , layers , weights , names ) :
    """Convert selu layer .
 Args :
 params : dictionary with layer parameters
 w _ name : name prefix in state _ dict
 scope _ name : pytorch scope name
 inputs : pytorch node inputs
 layers : dictionary with keras tensors
 weights : pytorch state _ dict
 names : use short names for keras layers"""

implementation:
print ( 'Converting selu ...' )
if names == 'short' :
    tf_name = 'SELU' + random_string ( 4 )
elif names == 'keep' :
    tf_name = w_name
else :
    tf_name = w_name + str ( random . random ( ) )
selu = keras . layers . Activation ( 'selu' , name = tf_name )
layers [ scope_name ] = selu ( layers [ inputs [ 0 ] ] )


signature:
def convert_upsample_bilinear ( params , w_name , scope_name , inputs , layers , weights , names ) :
    """Convert upsample _ bilinear2d layer .
 Args :
 params : dictionary with layer parameters
 w _ name : name prefix in state _ dict
 scope _ name : pytorch scope name
 inputs : pytorch node inputs
 layers : dictionary with keras tensors
 weights : pytorch state _ dict
 names : use short names for keras layers"""

implementation:
print ( 'Converting upsample...' )
if names == 'short' :
    tf_name = 'UPSL' + random_string ( 4 )
elif names == 'keep' :
    tf_name = w_name
else :
    tf_name = w_name + str ( random . random ( ) )
output_size = params [ 'output_size' ]
align_corners = params [ 'align_corners' ] > 0
def target_layer ( x , size = output_size , align_corners = align_corners ) :
    import tensorflow as tf
    x = tf . transpose ( x , [ 0 , 2 , 3 , 1 ] )
    x = tf . image . resize_images ( x , size , align_corners = align_corners )
    x = tf . transpose ( x , [ 0 , 3 , 1 , 2 ] )
    return x
lambda_layer = keras . layers . Lambda ( target_layer )
layers [ scope_name ] = lambda_layer ( layers [ inputs [ 0 ] ] )


signature:
def convert_upsample ( params , w_name , scope_name , inputs , layers , weights , names ) :
    """Convert nearest upsampling layer .
 Args :
 params : dictionary with layer parameters
 w _ name : name prefix in state _ dict
 scope _ name : pytorch scope name
 inputs : pytorch node inputs
 layers : dictionary with keras tensors
 weights : pytorch state _ dict
 names : use short names for keras layers"""

implementation:
print ( 'Converting upsample...' )
if params [ 'mode' ] != 'nearest' :
    raise AssertionError ( 'Cannot convert non-nearest upsampling' )
if names == 'short' :
    tf_name = 'UPSL' + random_string ( 4 )
elif names == 'keep' :
    tf_name = w_name
else :
    tf_name = w_name + str ( random . random ( ) )
if 'height_scale' in params :
    scale = ( params [ 'height_scale' ] , params [ 'width_scale' ] )
elif len ( inputs ) == 2 :
    scale = layers [ inputs [ - 1 ] + '_np' ] [ - 2 : ]
upsampling = keras . layers . UpSampling2D ( size = scale , name = tf_name )
layers [ scope_name ] = upsampling ( layers [ inputs [ 0 ] ] )


signature:
def convert_gather ( params , w_name , scope_name , inputs , layers , weights , names ) :
    """Convert gather ( embedding ) layer .
 Args :
 params : dictionary with layer parameters
 w _ name : name prefix in state _ dict
 scope _ name : pytorch scope name
 inputs : pytorch node inputs
 layers : dictionary with keras tensors
 weights : pytorch state _ dict
 names : use short names for keras layers"""

implementation:
print ( 'Converting embedding ...' )
if names == 'short' :
    tf_name = 'EMBD' + random_string ( 4 )
elif names == 'keep' :
    tf_name = w_name
else :
    tf_name = w_name + str ( random . random ( ) )
weights_name = '{0}.weight' . format ( w_name )
W = weights [ weights_name ] . numpy ( )
input_channels , output_channels = W . shape
keras_weights = [ W ]
dense = keras . layers . Embedding ( input_channels , weights = keras_weights , output_dim = output_channels , name = tf_name )
layers [ scope_name ] = dense ( layers [ inputs [ 1 ] ] )


signature:
def set_training ( model , mode ) :
    """A context manager to temporarily set the training mode of ' model '
 to ' mode ' , resetting it when we exit the with - block . A no - op if
 mode is None ."""

implementation:
if mode is None :
    yield
    return
old_mode = model . training
if old_mode != mode :
    model . train ( mode )
try :
    yield
finally :
    if old_mode != mode :
        model . train ( old_mode )


signature:
def pytorch_to_keras ( model , args , input_shapes , change_ordering = False , training = False , verbose = False , names = False , ) :
    """By given pytorch model convert layers with specified convertors .
 Args :
 model : pytorch model
 args : pytorch model arguments
 input _ shapes : keras input shapes ( using for each InputLayer )
 change _ ordering : change CHW to HWC
 training : switch model to training mode
 verbose : verbose output
 names : use short names , use random - suffix or keep original names for keras layers
 Returns :
 model : created keras model ."""

implementation:
# PyTorch JIT tracing
if isinstance ( args , torch . autograd . Variable ) :
    args = ( args , )
# Workaround for previous versions
if isinstance ( input_shapes , tuple ) :
    input_shapes = [ input_shapes ]
orig_state_dict_keys = _unique_state_dict ( model ) . keys ( )
with set_training ( model , training ) :
    trace , torch_out = torch . jit . get_trace_graph ( model , tuple ( args ) )
if orig_state_dict_keys != _unique_state_dict ( model ) . keys ( ) :
    raise RuntimeError ( "state_dict changed after running the tracer; " "something weird is happening in your model!" )
# _ optimize _ trace ( trace , False )
if version . parse ( '0.4.0' ) < version . parse ( torch . __version__ ) :
    trace . set_graph ( _optimize_graph ( trace . graph ( ) , OperatorExportTypes . ONNX ) )
else :
    trace . set_graph ( _optimize_graph ( trace . graph ( ) , False ) )
trace . graph ( ) . lint ( )
if verbose :
    print ( trace . graph ( ) )
# Get all graph nodes
nodes = list ( trace . graph ( ) . nodes ( ) )
# Optimize Flatten :
# When we have something loke that :
# %523 : Long ( ) = onnx : : Constant [ value = { 0 } ] ( ) , scope : ResNet
# %524 : Dynamic = onnx : : Shape ( % 522 ) , scope : ResNet
# %526 : Long ( ) = onnx : : Gather [ axis = 0 ] ( % 524 , % 523 ) , scope : ResNet
# %527 : Long ( ) = onnx : : Constant [ value = { - 1 } ] ( ) , scope : ResNet
# %534 : Dynamic = onnx : : Unsqueeze [ axes = [ 0 ] ] ( % 526)
# %535 : Dynamic = onnx : : Unsqueeze [ axes = [ 0 ] ] ( % 527)
# %536 : Dynamic = onnx : : Concat [ axis = 0 ] ( % 534 , % 535)
# %529 : Float ( 1 , 512 ) = onnx : : Reshape ( % 522 , % 536 ) , scope : ResNet
# It ' s better to replace it with onnx : : Flatten
if six . PY3 :
    from types import SimpleNamespace
    seq_to_find = [ 'onnx::Constant' , 'onnx::Shape' , 'onnx::Gather' , 'onnx::Constant' , 'onnx::Unsqueeze' , 'onnx::Unsqueeze' , 'onnx::Concat' , 'onnx::Reshape' ]
    k = 0
    s = 0
    for i , node in enumerate ( nodes ) :
        if node . kind ( ) == seq_to_find [ k ] :
            if k == 0 :
                s = i
            k += 1
            if k == len ( seq_to_find ) :
                reshape_op = nodes [ s + k - 1 ]
                flatten_op = { 'kind' : ( lambda : 'onnx::Flatten' ) , 'attributeNames' : ( lambda : { } ) , 'outputs' : ( lambda : list ( reshape_op . outputs ( ) ) ) , 'scopeName' : ( lambda : reshape_op . scopeName ( ) ) , 'inputs' : ( lambda : list ( reshape_op . inputs ( ) ) [ : 1 ] ) , '__str__' : ( lambda : reshape_op . __str__ ( ) ) , }
                nodes = nodes [ : s ] + [ SimpleNamespace ( ** flatten_op ) ] + nodes [ s + k : ]
                break
        else :
            k = 0
            s = - 1
# Collect graph inputs and outputs
graph_outputs = [ get_leaf_id ( n ) for n in trace . graph ( ) . outputs ( ) ]
graph_inputs = [ get_leaf_id ( n ) for n in trace . graph ( ) . inputs ( ) ]
# Collect model state dict
state_dict = _unique_state_dict ( model )
if verbose :
    print ( 'Graph inputs:' , graph_inputs )
    print ( 'Graph outputs:' , graph_outputs )
    print ( 'State dict:' , list ( state_dict ) )
import re
import keras
from keras import backend as K
K . set_image_data_format ( 'channels_first' )
layers = dict ( )
keras_inputs = [ ]
for i in range ( len ( args ) ) :
    layers [ graph_inputs [ i ] ] = keras . layers . InputLayer ( input_shape = input_shapes [ i ] , name = 'input{0}' . format ( i ) ) . output
    keras_inputs . append ( layers [ graph_inputs [ i ] ] )
outputs = [ ]
group_indices = defaultdict ( lambda : 0 , { } )
for node in nodes :
    node_inputs = list ( node . inputs ( ) )
    node_input_names = [ ]
    for node_input in node_inputs :
        node_input_names . append ( get_leaf_id ( node_input ) )
    node_type = node . kind ( )
    node_scope_name = node . scopeName ( )
    node_id = get_node_id ( node )
    node_name_regex = re . findall ( r'\[([\w\d.\-\[\]\s]+)\]' , node_scope_name )
    try :
        int ( node_name_regex [ - 1 ] )
        node_weigth_group_name = '.' . join ( node_name_regex [ : - 1 ] )
        node_weights_name = node_weigth_group_name + '.' + str ( group_indices [ node_weigth_group_name ] )
        group_indices [ node_weigth_group_name ] += 1
    except ValueError :
        node_weights_name = '.' . join ( node_name_regex )
    except IndexError :
        node_weights_name = '.' . join ( node_input_names )
    node_attrs = { k : node [ k ] for k in node . attributeNames ( ) }
    node_outputs = list ( node . outputs ( ) )
    node_outputs_names = [ ]
    for node_output in node_outputs :
        if node_output . node ( ) . scopeName ( ) :
            node_outputs_names . append ( node_output . node ( ) . scopeName ( ) )
    if verbose :
        print ( ' ____ ' )
        print ( 'graph node:' , node_scope_name )
        print ( 'node id:' , node_id )
        print ( 'type:' , node_type )
        print ( 'inputs:' , node_input_names )
        print ( 'outputs:' , node_outputs_names )
        print ( 'name in state_dict:' , node_weights_name )
        print ( 'attrs:' , node_attrs )
        print ( 'is_terminal:' , node_id in graph_outputs )
    AVAILABLE_CONVERTERS [ node_type ] ( node_attrs , node_weights_name , node_id , node_input_names , layers , state_dict , names )
    if node_id in graph_outputs :
        outputs . append ( layers [ node_id ] )
model = keras . models . Model ( inputs = keras_inputs , outputs = outputs )
if change_ordering :
    import numpy as np
    conf = model . get_config ( )
    for layer in conf [ 'layers' ] :
        if layer [ 'config' ] and 'batch_input_shape' in layer [ 'config' ] :
            layer [ 'config' ] [ 'batch_input_shape' ] = tuple ( np . reshape ( np . array ( [ [ None ] + list ( layer [ 'config' ] [ 'batch_input_shape' ] [ 2 : ] [ : ] ) + [ layer [ 'config' ] [ 'batch_input_shape' ] [ 1 ] ] ] ) , - 1 ) )
        if layer [ 'config' ] and 'target_shape' in layer [ 'config' ] :
            if len ( list ( layer [ 'config' ] [ 'target_shape' ] [ 1 : ] [ : ] ) ) > 0 :
                layer [ 'config' ] [ 'target_shape' ] = tuple ( np . reshape ( np . array ( [ list ( layer [ 'config' ] [ 'target_shape' ] [ 1 : ] [ : ] ) , layer [ 'config' ] [ 'target_shape' ] [ 0 ] ] ) , - 1 ) , )
        if layer [ 'config' ] and 'data_format' in layer [ 'config' ] :
            layer [ 'config' ] [ 'data_format' ] = 'channels_last'
        if layer [ 'config' ] and 'axis' in layer [ 'config' ] :
            layer [ 'config' ] [ 'axis' ] = 3
    K . set_image_data_format ( 'channels_last' )
    model_tf_ordering = keras . models . Model . from_config ( conf )
    # from keras . utils . layer _ utils import convert _ all _ kernels _ in _ model
    # convert _ all _ kernels _ in _ model ( model )
    for dst_layer , src_layer in zip ( model_tf_ordering . layers , model . layers ) :
        dst_layer . set_weights ( src_layer . get_weights ( ) )
    model = model_tf_ordering
print ( 'Your model was (probably) successfully converted! ' 'Please, follow the repository https://github.com/nerox8664/pytorch2keras and give a star :)' )
return model


signature:
def get_platform_pwm ( ** keywords ) :
    """Attempt to return a PWM instance for the platform which the code is being
 executed on . Currently supports only the Raspberry Pi using the RPi . GPIO
 library and Beaglebone Black using the Adafruit _ BBIO library . Will throw an
 exception if a PWM instance can ' t be created for the current platform . The
 returned PWM object has the same interface as the RPi _ PWM _ Adapter and
 BBIO _ PWM _ Adapter classes ."""

implementation:
plat = Platform . platform_detect ( )
if plat == Platform . RASPBERRY_PI :
    import RPi . GPIO
    return RPi_PWM_Adapter ( RPi . GPIO , ** keywords )
elif plat == Platform . BEAGLEBONE_BLACK :
    import Adafruit_BBIO . PWM
    return BBIO_PWM_Adapter ( Adafruit_BBIO . PWM , ** keywords )
elif plat == Platform . UNKNOWN :
    raise RuntimeError ( 'Could not determine platform.' )


signature:
def start ( self , pin , dutycycle , frequency_hz = 2000 ) :
    """Enable PWM output on specified pin . Set to intiial percent duty cycle
 value ( 0.0 to 100.0 ) and frequency ( in Hz ) ."""

implementation:
if dutycycle < 0.0 or dutycycle > 100.0 :
    raise ValueError ( 'Invalid duty cycle value, must be between 0.0 to 100.0 (inclusive).' )
# Make pin an output .
self . rpi_gpio . setup ( pin , self . rpi_gpio . OUT )
# Create PWM instance and save a reference for later access .
self . pwm [ pin ] = self . rpi_gpio . PWM ( pin , frequency_hz )
# Start the PWM at the specified duty cycle .
self . pwm [ pin ] . start ( dutycycle )


signature:
def set_duty_cycle ( self , pin , dutycycle ) :
    """Set percent duty cycle of PWM output on specified pin . Duty cycle must
 be a value 0.0 to 100.0 ( inclusive ) ."""

implementation:
if dutycycle < 0.0 or dutycycle > 100.0 :
    raise ValueError ( 'Invalid duty cycle value, must be between 0.0 to 100.0 (inclusive).' )
if pin not in self . pwm :
    raise ValueError ( 'Pin {0} is not configured as a PWM.  Make sure to first call start for the pin.' . format ( pin ) )
self . pwm [ pin ] . ChangeDutyCycle ( dutycycle )


signature:
def set_frequency ( self , pin , frequency_hz ) :
    """Set frequency ( in Hz ) of PWM output on specified pin ."""

implementation:
if pin not in self . pwm :
    raise ValueError ( 'Pin {0} is not configured as a PWM.  Make sure to first call start for the pin.' . format ( pin ) )
self . pwm [ pin ] . ChangeFrequency ( frequency_hz )


signature:
def stop ( self , pin ) :
    """Stop PWM output on specified pin ."""

implementation:
if pin not in self . pwm :
    raise ValueError ( 'Pin {0} is not configured as a PWM.  Make sure to first call start for the pin.' . format ( pin ) )
self . pwm [ pin ] . stop ( )
del self . pwm [ pin ]


implementation:
if dutycycle < 0.0 or dutycycle > 100.0 :
    raise ValueError ( 'Invalid duty cycle value, must be between 0.0 to 100.0 (inclusive).' )
self . bbio_pwm . start ( pin , dutycycle , frequency_hz )


implementation:
if dutycycle < 0.0 or dutycycle > 100.0 :
    raise ValueError ( 'Invalid duty cycle value, must be between 0.0 to 100.0 (inclusive).' )
self . bbio_pwm . set_duty_cycle ( pin , dutycycle )


signature:
def platform_detect ( ) :
    """Detect if running on the Raspberry Pi or Beaglebone Black and return the
 platform type . Will return RASPBERRY _ PI , BEAGLEBONE _ BLACK , or UNKNOWN ."""

implementation:
# Handle Raspberry Pi
pi = pi_version ( )
if pi is not None :
    return RASPBERRY_PI
# Handle Beaglebone Black
# TODO : Check the Beaglebone Black / proc / cpuinfo value instead of reading
# the platform .
plat = platform . platform ( )
if plat . lower ( ) . find ( 'armv7l-with-debian' ) > - 1 :
    return BEAGLEBONE_BLACK
elif plat . lower ( ) . find ( 'armv7l-with-ubuntu' ) > - 1 :
    return BEAGLEBONE_BLACK
elif plat . lower ( ) . find ( 'armv7l-with-glibc2.4' ) > - 1 :
    return BEAGLEBONE_BLACK
elif plat . lower ( ) . find ( 'tegra-aarch64-with-ubuntu' ) > - 1 :
    return JETSON_NANO
# Handle Minnowboard
# Assumption is that mraa is installed
try :
    import mraa
    if mraa . getPlatformName ( ) == 'MinnowBoard MAX' :
        return MINNOWBOARD
except ImportError :
    pass
# Couldn ' t figure out the platform , just return unknown .
return UNKNOWN


signature:
def set_bit_order ( self , order ) :
    """Set order of bits to be read / written over serial lines . Should be
 either MSBFIRST for most - significant first , or LSBFIRST for
 least - signifcant first ."""

implementation:
if order == MSBFIRST :
    self . _device . lsbfirst = False
elif order == LSBFIRST :
    self . _device . lsbfirst = True
else :
    raise ValueError ( 'Order must be MSBFIRST or LSBFIRST.' )


signature:
def set_mode ( self , mode ) :
    """Set SPI mode which controls clock polarity and phase . Should be a
 numeric value 0 , 1 , 2 , or 3 . See wikipedia page for details on meaning :
 http : / / en . wikipedia . org / wiki / Serial _ Peripheral _ Interface _ Bus"""

implementation:
if mode < 0 or mode > 3 :
    raise ValueError ( 'Mode must be a value 0, 1, 2, or 3.' )
self . _device . mode ( mode )


implementation:
if mode < 0 or mode > 3 :
    raise ValueError ( 'Mode must be a value 0, 1, 2, or 3.' )
if mode & 0x02 : # Clock is normally high in mode 2 and 3.
    self . _clock_base = GPIO . HIGH
else : # Clock is normally low in mode 0 and 1.
    self . _clock_base = GPIO . LOW
if mode & 0x01 : # Read on trailing edge in mode 1 and 3.
    self . _read_leading = False
else : # Read on leading edge in mode 0 and 2.
    self . _read_leading = True
# Put clock into its base state .
self . _gpio . output ( self . _sclk , self . _clock_base )


implementation:
# Set self . _ mask to the bitmask which points at the appropriate bit to
# read or write , and appropriate left / right shift operator function for
# reading / writing .
if order == MSBFIRST :
    self . _mask = 0x80
    self . _write_shift = operator . lshift
    self . _read_shift = operator . rshift
elif order == LSBFIRST :
    self . _mask = 0x01
    self . _write_shift = operator . rshift
    self . _read_shift = operator . lshift
else :
    raise ValueError ( 'Order must be MSBFIRST or LSBFIRST.' )


signature:
def write ( self , data , assert_ss = True , deassert_ss = True ) :
    """Half - duplex SPI write . If assert _ ss is True , the SS line will be
 asserted low , the specified bytes will be clocked out the MOSI line , and
 if deassert _ ss is True the SS line be put back high ."""

implementation:
# Fail MOSI is not specified .
if self . _mosi is None :
    raise RuntimeError ( 'Write attempted with no MOSI pin specified.' )
if assert_ss and self . _ss is not None :
    self . _gpio . set_low ( self . _ss )
for byte in data :
    for i in range ( 8 ) : # Write bit to MOSI .
        if self . _write_shift ( byte , i ) & self . _mask :
            self . _gpio . set_high ( self . _mosi )
        else :
            self . _gpio . set_low ( self . _mosi )
        # Flip clock off base .
        self . _gpio . output ( self . _sclk , not self . _clock_base )
        # Return clock to base .
        self . _gpio . output ( self . _sclk , self . _clock_base )
if deassert_ss and self . _ss is not None :
    self . _gpio . set_high ( self . _ss )