Skip to content

Commit

Permalink
Merge pull request #4 from compas-dev/docs
Browse files Browse the repository at this point in the history
Documentation: clean up and added examples
  • Loading branch information
gonzalocasas authored Oct 31, 2023
2 parents c584636 + 42a33e5 commit b6a7235
Show file tree
Hide file tree
Showing 24 changed files with 531 additions and 26 deletions.
5 changes: 5 additions & 0 deletions .bumpversion.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ message = Bump version to {new_version}
commit = True
tag = True


[bumpversion:file:docs/installation.rst]
search = {current_version}
replace = {new_version}

[bumpversion:file:setup.py]
search = version="{current_version}"
replace = version="{new_version}"
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

* Added examples and more detailed documentation for installation and usage.

### Changed

* Fixed bug failing to get a `str` representation of `Message` on `ipy`
Expand Down
2 changes: 2 additions & 0 deletions docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ API Reference
:maxdepth: 1

api/compas_eve
api/compas_eve.mqtt
api/compas_eve.memory
2 changes: 2 additions & 0 deletions docs/api/compas_eve.memory.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

.. automodule:: compas_eve.memory
2 changes: 2 additions & 0 deletions docs/api/compas_eve.mqtt.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

.. automodule:: compas_eve.mqtt
3 changes: 3 additions & 0 deletions docs/api/compas_eve.rst
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
********************************************************************************
compas_eve
********************************************************************************

.. automodule:: compas_eve
27 changes: 21 additions & 6 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,18 @@ def setup(app):
# autosummary options

autosummary_generate = True
autosummary_mock_imports = [
"System",
"clr",
"Eto",
"Rhino",
"Grasshopper",
"scriptcontext",
"rhinoscriptsyntax",
"bpy",
"bmesh",
"mathutils",
]

# napoleon options

Expand Down Expand Up @@ -161,14 +173,17 @@ def linkcode_resolve(domain, info):
obj = getattr(module, obj_name)
attr = getattr(obj, attr_name)
if inspect.isfunction(attr):
filename = inspect.getmodule(obj).__name__.replace(".", "/")
lineno = inspect.getsourcelines(attr)[1]
try:
filename = inspect.getmodule(obj).__name__.replace(".", "/")
lineno = inspect.getsourcelines(attr)[1]
except IOError:
return None
else:
return None
else:
return None

return f"https://github.com/compas-dev/compas_eve/blob/master/src/{filename}.py#L{lineno}"
return f"https://github.com/gramaziokohler/compas_eve/blob/main/src/{filename}.py#L{lineno}"


# extlinks
Expand All @@ -185,9 +200,9 @@ def linkcode_resolve(domain, info):
"package_title": project,
"package_version": release,
"package_author": "Gonzalo Casas",
"package_docs": "https://compas-dev.github.io/compas_eve/",
"package_repo": "https://github.com/compas-dev/compas_eve",
"package_old_versions_txt": "https://compas-dev.github.io/compas_eve/doc_versions.txt",
"package_docs": "https://gramaziokohler.github.io/compas_eve/",
"package_repo": "https://github.com/gramaziokohler/compas_eve",
"package_old_versions_txt": "https://gramaziokohler.github.io/compas_eve/doc_versions.txt",
}

html_context = {}
Expand Down
82 changes: 77 additions & 5 deletions docs/examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,81 @@
Examples
********************************************************************************

.. toctree::
:maxdepth: 1
:titlesonly:
:glob:
.. currentmodule:: compas_eve

examples/*
The main feature of ``compas_eve`` is to allow communication between different
parts of a program using messages. These messages are sent around using a
publisher/subscriber model, or pub/sub for short. In pub/sub communication,
messages are not sent directly from a sender to a receiver, instead, they are
sent to a :class:`Topic`. A topic is like a mailbox, the :class:`Publisher`
sends messages to the topic without the need for a subcriber to be
actively listening for messages, and also the :class:`Subscriber` can start
listening for messages on a topic without the need for any publisher to be
currently sending anything.

This creates a highly decoupled communication model that facilitates the creation
of complex software with simple code.

An additional benefit of pub/sub is that it is not limited to 1-to-1 communication:
on a single topic, there can be multiple publishers and multiple subscribers all
communicating at the same time without additional coordination.

Hello World
-----------

Let's see a **Hello World** example of this type of communication using ``compas_eve``.
This example is very contrived because both the publisher and the subscriber are defined
in the same script and the same thread.

.. literalinclude :: examples/01_hello_world.py
:language: python
This example is the simplest possible, and it only shows the main concepts needed
to communicate. In particular, ``compas_eve`` uses by default an **in-memory transport**
for the messages, this means that messages are can only be received within the same program.

Hello Threaded World
--------------------

Let's try to extend this first example and add multiple threads to illustrate
multi-threaded communication:

.. literalinclude :: examples/02_hello_threaded_world.py
:language: python
This get more interesting! Now the publisher and subscriber are in separate threads. However,
the in-memory transport is limited to *same-process*. This means that if we launch this
script twice, the messages will not jump from one process to the other.
In other words, if we want to communicate with a subscriber on a different process on the machine,
or even on a completely separate machine, we need to take an extra step.

Hello Distributed World
-----------------------

Fortunately, it is very easy to extend our example and enable communication across processes, machines,
networks, continents, anything that is connected to the Internet!

The only difference is that we are going to configure a different :class:`Transport` implementation for
our messages. In this case, we will use the MQTT transport method. `MQTT <https://en.wikipedia.org/wiki/MQTT>`_
is a network protocol very popular for IoT applications because of its lightweight.

We are going to split the code and create one script for sending messages with a publisher and a different
one for receiving. This will enable us to start the two examples at the same time from different windows, or
potentially from different machines!

First the publisher example:

.. literalinclude :: examples/03_hello_distributed_world_pub.py
:language: python
And now the subscriber example:

.. literalinclude :: examples/03_hello_distributed_world_sub.py
:language: python
You can start both programs in two completely different terminal windows,
or even completely different computers and they will be able to communicate!

And since pub/sub allows any number of publishers and any number of
subscriber per topic, you can start the same scripts more than once and the
messages will be received and send multiple times!
19 changes: 19 additions & 0 deletions docs/examples/01_hello_world.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import time

from compas_eve import Message
from compas_eve import Publisher
from compas_eve import Subscriber
from compas_eve import Topic


topic = Topic("/compas_eve/hello_world/", Message)

publisher = Publisher(topic)
subcriber = Subscriber(topic, callback=lambda msg: print(f"Received message: {msg.text}"))
subcriber.subscribe()

for i in range(20):
msg = Message(text=f"Hello world #{i}")
print(f"Publishing message: {msg.text}")
publisher.publish(msg)
time.sleep(1)
37 changes: 37 additions & 0 deletions docs/examples/02_hello_threaded_world.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import time
from threading import Thread

from compas_eve import Message
from compas_eve import Publisher
from compas_eve import Subscriber
from compas_eve import Topic

topic = Topic("/compas_eve/hello_world/", Message)


def start_publisher():
publisher = Publisher(topic)

for i in range(20):
msg = Message(text=f"Hello world #{i}")
print(f"Publishing message: {msg.text}")
publisher.publish(msg)
time.sleep(1)


def start_subscriber():
subcriber = Subscriber(topic, callback=lambda msg: print(f"Received message: {msg.text}"))
subcriber.subscribe()


# Define one thread for each
t1 = Thread(target=start_subscriber)
t2 = Thread(target=start_publisher)

# Start both threads
t1.start()
t2.start()

# Wait until both threads complete
t1.join()
t2.join()
17 changes: 17 additions & 0 deletions docs/examples/03_hello_distributed_world_pub.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import time

from compas_eve import Message
from compas_eve import Publisher
from compas_eve import Topic
from compas_eve.mqtt import MqttTransport

topic = Topic("/compas_eve/hello_world/", Message)
tx = MqttTransport("broker.hivemq.com")

publisher = Publisher(topic, transport=tx)

for i in range(20):
msg = Message(text=f"Hello world #{i}")
print(f"Publishing message: {msg.text}")
publisher.publish(msg)
time.sleep(1)
16 changes: 16 additions & 0 deletions docs/examples/03_hello_distributed_world_sub.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import time

from compas_eve import Message
from compas_eve import Subscriber
from compas_eve import Topic
from compas_eve.mqtt import MqttTransport

topic = Topic("/compas_eve/hello_world/", Message)
tx = MqttTransport("broker.hivemq.com")

subcriber = Subscriber(topic, callback=lambda msg: print(f"Received message: {msg.text}"), transport=tx)
subcriber.subscribe()

print("Waiting for messages, press CTRL+C to cancel")
while True:
time.sleep(1)
Empty file removed docs/examples/PLACEHOLDER
Empty file.
7 changes: 3 additions & 4 deletions docs/index.rst
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
********************************************************************************
compas_eve
Event Extensions for COMPAS
********************************************************************************

.. rst-class:: lead

COMPAS Event Extensions: adds event-based communication infrastructure to the COMPAS framework.
``compas_eve`` adds event-based communication infrastructure to the COMPAS framework.

.. .. figure:: /_images/
:figclass: figure
Expand All @@ -15,12 +15,11 @@ Table of Contents
=================

.. toctree::
:maxdepth: 3
:maxdepth: 2
:titlesonly:

Introduction <self>
installation
tutorial
examples
api
license
Expand Down
Loading

0 comments on commit b6a7235

Please sign in to comment.