net package

Submodules

net.api module

api module

Contains the general network interactions for net.

net.api.peers(refresh=False, groups=None, on_host=False, hubs_only=False)[source]

Get a list of all peers on your network. This is a cached values since the call to graph the network can be long. You can also limit this search to only look for operating peers on the localhost which does not require the long network scan, just set the on_host kwarg to True.

Hubs act as the centers for certain application events or processes. In some cases, you may only want to subscribe or communicate with hubs. You can specify this through the hubs_only kwarg.

The initial call to this will hang for a few seconds. Under the hood, it is making a shell call to arp -a which will walk your network and find all hosts.

Standard call to get the peers on your network.

all_peers = net.peers()

Only search for peers on local host and not on the network.

all_peers = net.peers(on_host=True)

Refresh all peers in the cache

all_peers = net.peers(refresh=True)

Refresh the cache with peers in group1

all_peers = net.peers("group1", refresh=True)

Refresh the cache with peers in group1 and 2

all_peers = net.peers(["group1", "group2"], refresh=True)

Refresh the cache with all of the hubs on the network regardless of group.

all_peers = net.peers(hubs_only=True, refresh=True)

Refresh the cache with only hubs in group1 and 2

all_peers = net.peers(["group1", "group2"], hubs_only=True, refresh=True)
Parameters:
  • refresh – Bool
  • groups – str
  • on_host – Bool
  • hubs_only – Bool
Returns:

{

# Peers ‘peers’: {

b’MTkyLjE2OC4yLjI0OjMwMTAgLT4gTm9uZQ==’: {

‘group’: ‘None’, ‘host’: ‘192.168.2.24’, ‘port’: 3010, ‘hub’: False, ‘executable’: path/to/executable, ‘user’: username

},

},

# Groups ‘None’: [

b’MTkyLjE2OC4yLjI0OjMwMTAgLT4gTm9uZQ==’

]

}

net.cli module

Console script for net.

net.connect module

Connect Module

Contains the connect decorator and should have nothing else.

net.connect.connect(tag=None)[source]

Registers a function as a connection. This will be tagged and registered with the Peer server. The tag is a base64 encoded path to the function or can be manually tagged with the tag parameter. Tagging a named function allows you to interconnect functions between code bases.

For example, a connected function with no tag is tied to the func.__module__ + func.__name__. This means the peers will only know which functions are compatible based on the namespace staying the same.

# app version 1 running on PeerA
app/
  module/
    function

# app version 2 running on PeerB
app/
  module/
    function2 <- # renamed from function

In the above example, PeerA could make a request to PeerB to execute “app.module.function”. But that function no longer exists as far as PeerB is concerned. The source code and functionality could be exactly the same, but the logical location is different and therefore will fail.

# app version 1 running on PeerA
app/
  module/
    function (tagged: "MyTaggedFunction")

# app version 2 running on PeerB
app/
  module/
    function2 (tagged: "MyTaggedFunction")

In the above example, we have tagged function and function2 with the same tag, “MyTaggedFunction”. Now when PeerA requests to execute, it will request that PeerB executes “MyTaggedFunction” which is attached to the new renamed function.

Standard no tagging

@net.connect()
def your_function(some_value):
    return some_value

Custom tagging

@net.connect("MyTaggedFunction")
def your_function(some_value):
    return some_value

net.environment module

Handler Module

Contains the peer handler and should have nothing else.

net.event module

Event Module

Contains the event decorator and should have nothing else.

net.event.event(name)[source]

Registers a function as an event trigger. Event triggers are hooks into the event system between peers. Peers that net.subscribe to a peer, register an event on that peer.

Lets say PeerA subscribes to an event on PeerB using the following code.

# code on PeerA

peerB_id = "peerb"

@net.subscribe("doing_something")
def handleEvent(whatPeerBDid):
    ...do something

The subscribe decorator has communicated with PeerB and registered itself as on the list of peer to update if “doing_something” is ever triggered. On PeerB’s side we have the following.

# code on PeerB

@net.event("doing_something")
def imDoingSomething(*args, **kwargs):
    return args, kwargs

Note

All functions flagged as an event MUST return args and kwargs exactly as displayed above.

Now lets say in PeerB we want to trigger the event in a for loop and have it hand off the values to all the subscribed peers, PeerA in this case.

for i in range(0, 10):
    imDoingSomething(i)  # <- this will notify PeerA and pass the value of 'i'.

Keep in mind, you can have any number of peers subscribe to any kind of event. So if we had 5 peers subscribe to PeerB they would all be passed this value at runtime.

Lastly, these event functions act as a buffer between the runtime code of your application and the delivery of the content to the peer. For example:

var = MyCustomObject()  # some JSON incompatible object

...do a bunch of delivery prep and muddy up the application code...

imDoingSomething(var)

Instead

@net.event("doing_something")
def imDoingSomething(*args, **kwargs):

    obj = args[0]

    ...clean and prepare for transit here...

    args[0] = cleanedObj

    return args, kwargs

As you can see, these functions act as a hook into the delivery system when the event is triggered.

There are protections put in place to try to prevent the peer that triggered the event to be blocked by a bad handle on the subscribed peer. For the purpose of protecting the event triggering peer from remote errors, all connection errors and remote runtime errors will be caught and logged. But nothing will halt the running application.

i.e. event -> remote peer errors -> event peer will log and ignore

Stale peer subscriptions will be added to the stale list and pruned. Since the subscriptions are created per client request, the event peer will not know until a request is made that the subscribed peer went offline.

net.flag module

Flag Module

Contains the flag decorator and should have nothing else.

net.flag.flag(name)[source]

Register a function as a flag handler for the peer server.

Parameters:name – str

net.handler module

Handler Module

Contains the peer handler and should have nothing else.

class net.handler.PeerHandler(request, client_address, server)[source]

Bases: socketserver.BaseRequestHandler

Handles all incoming requests to the applications Peer server. Do not modify or interact with directly.

handle()[source]

Handles all incoming requests to the server.

net.imports module

python 2/3 imports handled here

exception net.imports.ConnectionRefusedError

Bases: ConnectionError

Connection refused.

net.peer module

net.peer.Peer(*args, **kwargs)[source]

Running Peer server for this instance of python.

Returns:net.peer._Peer

net.subscribe module

Subscribe Module

Contains the subscribe decorator and should have nothing else.

net.subscribe.subscribe(event, groups=None, hubs_only=False, peers=None, on_host=None)[source]

Subscribe to an event on another peer or set of peers. When the peer triggers an event using net.event, the peer will take the arguments passed and forward them to this function. By default, this will subscribe to all peers. You can also manually filter the peers by selectively passing in only the peers you want to subscribe to using the peers keyword argument.

Subscribe to “some_event” on group1 peers only.

group1_peers = net.peers(groups=['group1'])

@net.subscribe("some_event", group1_peers)
def your_function(subscription_args, subscription_kwarg=None):
    return some_value

Subscribe to “some_event” on a single peer.

peer = net.peers()[0]

@net.subscribe("some_event", peer)
def your_function(subscription_args, subscription_kwarg=None):
    return some_value

Subscribe to “some_event” on all peers.

@net.subscribe("some_event")
def your_function(subscription_args, subscription_kwarg=None):
    return some_value

Module contents

Top-level package for net.

net.connect(tag=None)[source]

Registers a function as a connection. This will be tagged and registered with the Peer server. The tag is a base64 encoded path to the function or can be manually tagged with the tag parameter. Tagging a named function allows you to interconnect functions between code bases.

For example, a connected function with no tag is tied to the func.__module__ + func.__name__. This means the peers will only know which functions are compatible based on the namespace staying the same.

# app version 1 running on PeerA
app/
  module/
    function

# app version 2 running on PeerB
app/
  module/
    function2 <- # renamed from function

In the above example, PeerA could make a request to PeerB to execute “app.module.function”. But that function no longer exists as far as PeerB is concerned. The source code and functionality could be exactly the same, but the logical location is different and therefore will fail.

# app version 1 running on PeerA
app/
  module/
    function (tagged: "MyTaggedFunction")

# app version 2 running on PeerB
app/
  module/
    function2 (tagged: "MyTaggedFunction")

In the above example, we have tagged function and function2 with the same tag, “MyTaggedFunction”. Now when PeerA requests to execute, it will request that PeerB executes “MyTaggedFunction” which is attached to the new renamed function.

Standard no tagging

@net.connect()
def your_function(some_value):
    return some_value

Custom tagging

@net.connect("MyTaggedFunction")
def your_function(some_value):
    return some_value
net.flag(name)[source]

Register a function as a flag handler for the peer server.

Parameters:name – str
net.Peer(*args, **kwargs)[source]

Running Peer server for this instance of python.

Returns:net.peer._Peer
net.null_response(connection, foreign_peer_id)[source]

Execute this if the peer has returned the NULL_RESPONSE flag.

Parameters:
  • connection – name of the connection requested
  • foreign_peer_id – The foreign peers friendly_id
Returns:

str

net.pass_through(*args, **kwargs)[source]

Used for testing, takes your arguments and passes them back for type testing.

variable = "Test this comes back the way I sent it."

response = net.pass_through(variable, peer='somepeer')
Returns:*args, **kwargs
net.null(*args, **kwargs)[source]

Return a null response flag

Returns:NULL Flag
net.info(*args, **kwargs)[source]

Return information about the peer requested.

friendly_information = net.info(peer='somepeer')
Returns:peer.friendly_id
net.invalid_connection(connection, foreign_peer_id)[source]

Execute this if the peer has returned the NULL_RESPONSE flag.

Parameters:
  • connection – name of the connection requested
  • foreign_peer_id – The foreign peers friendly_id
Returns:

net.subscribe(event, groups=None, hubs_only=False, peers=None, on_host=None)[source]

Subscribe to an event on another peer or set of peers. When the peer triggers an event using net.event, the peer will take the arguments passed and forward them to this function. By default, this will subscribe to all peers. You can also manually filter the peers by selectively passing in only the peers you want to subscribe to using the peers keyword argument.

Subscribe to “some_event” on group1 peers only.

group1_peers = net.peers(groups=['group1'])

@net.subscribe("some_event", group1_peers)
def your_function(subscription_args, subscription_kwarg=None):
    return some_value

Subscribe to “some_event” on a single peer.

peer = net.peers()[0]

@net.subscribe("some_event", peer)
def your_function(subscription_args, subscription_kwarg=None):
    return some_value

Subscribe to “some_event” on all peers.

@net.subscribe("some_event")
def your_function(subscription_args, subscription_kwarg=None):
    return some_value
net.event(name)[source]

Registers a function as an event trigger. Event triggers are hooks into the event system between peers. Peers that net.subscribe to a peer, register an event on that peer.

Lets say PeerA subscribes to an event on PeerB using the following code.

# code on PeerA

peerB_id = "peerb"

@net.subscribe("doing_something")
def handleEvent(whatPeerBDid):
    ...do something

The subscribe decorator has communicated with PeerB and registered itself as on the list of peer to update if “doing_something” is ever triggered. On PeerB’s side we have the following.

# code on PeerB

@net.event("doing_something")
def imDoingSomething(*args, **kwargs):
    return args, kwargs

Note

All functions flagged as an event MUST return args and kwargs exactly as displayed above.

Now lets say in PeerB we want to trigger the event in a for loop and have it hand off the values to all the subscribed peers, PeerA in this case.

for i in range(0, 10):
    imDoingSomething(i)  # <- this will notify PeerA and pass the value of 'i'.

Keep in mind, you can have any number of peers subscribe to any kind of event. So if we had 5 peers subscribe to PeerB they would all be passed this value at runtime.

Lastly, these event functions act as a buffer between the runtime code of your application and the delivery of the content to the peer. For example:

var = MyCustomObject()  # some JSON incompatible object

...do a bunch of delivery prep and muddy up the application code...

imDoingSomething(var)

Instead

@net.event("doing_something")
def imDoingSomething(*args, **kwargs):

    obj = args[0]

    ...clean and prepare for transit here...

    args[0] = cleanedObj

    return args, kwargs

As you can see, these functions act as a hook into the delivery system when the event is triggered.

There are protections put in place to try to prevent the peer that triggered the event to be blocked by a bad handle on the subscribed peer. For the purpose of protecting the event triggering peer from remote errors, all connection errors and remote runtime errors will be caught and logged. But nothing will halt the running application.

i.e. event -> remote peer errors -> event peer will log and ignore

Stale peer subscriptions will be added to the stale list and pruned. Since the subscriptions are created per client request, the event peer will not know until a request is made that the subscribed peer went offline.

net.connections(*args, **kwargs)[source]

Return the connections registered with the peer.

friendly_information = net.connections(peer='somepeer')
Returns:peer.CONNECTIONS