├── .gitmodules ├── tests ├── test_rostful │ ├── __init__.py │ ├── test_params.py │ ├── test_services.py │ ├── test_topics.py │ ├── test_frontend.py │ └── test_app.py └── __init__.py ├── doc ├── readme_link.rst ├── changelog_link.rst ├── weblinks.rst ├── internals.rst ├── index.rst └── tutorial.rst ├── MANIFEST.in ├── rostful ├── templates │ ├── security │ │ ├── email │ │ │ ├── reset_notice.txt │ │ │ ├── reset_notice.html │ │ │ ├── reset_instructions.html │ │ │ ├── reset_instructions.txt │ │ │ ├── confirmation_instructions.txt │ │ │ ├── login_instructions.txt │ │ │ ├── confirmation_instructions.html │ │ │ ├── login_instructions.html │ │ │ ├── welcome.txt │ │ │ ├── welcome.html │ │ │ ├── change_notice.txt │ │ │ └── change_notice.html │ │ ├── send_login.html │ │ ├── forgot_password.html │ │ ├── send_confirmation.html │ │ ├── reset_password.html │ │ ├── change_password.html │ │ ├── login_user.html │ │ └── register_user.html │ ├── error.html │ ├── layout.html │ ├── param.html │ ├── service.html │ ├── index.html │ └── topic.html ├── static │ ├── favicon.ico │ └── js │ │ ├── jquery-mobile │ │ └── images │ │ │ ├── ajax-loader.gif │ │ │ ├── icons-png │ │ │ ├── eye-black.png │ │ │ ├── eye-white.png │ │ │ ├── tag-black.png │ │ │ ├── tag-white.png │ │ │ ├── action-black.png │ │ │ ├── action-white.png │ │ │ ├── alert-black.png │ │ │ ├── alert-white.png │ │ │ ├── audio-black.png │ │ │ ├── audio-white.png │ │ │ ├── back-black.png │ │ │ ├── back-white.png │ │ │ ├── bars-black.png │ │ │ ├── bars-white.png │ │ │ ├── camera-black.png │ │ │ ├── camera-white.png │ │ │ ├── check-black.png │ │ │ ├── check-white.png │ │ │ ├── clock-black.png │ │ │ ├── clock-white.png │ │ │ ├── cloud-black.png │ │ │ ├── cloud-white.png │ │ │ ├── delete-black.png │ │ │ ├── delete-white.png │ │ │ ├── edit-black.png │ │ │ ├── edit-white.png │ │ │ ├── gear-black.png │ │ │ ├── gear-white.png │ │ │ ├── grid-black.png │ │ │ ├── grid-white.png │ │ │ ├── heart-black.png │ │ │ ├── heart-white.png │ │ │ ├── home-black.png │ │ │ ├── home-white.png │ │ │ ├── info-black.png │ │ │ ├── info-white.png │ │ │ ├── lock-black.png │ │ │ ├── lock-white.png │ │ │ ├── mail-black.png │ │ │ ├── mail-white.png │ │ │ ├── minus-black.png │ │ │ ├── minus-white.png │ │ │ ├── phone-black.png │ │ │ ├── phone-white.png │ │ │ ├── plus-black.png │ │ │ ├── plus-white.png │ │ │ ├── power-black.png │ │ │ ├── power-white.png │ │ │ ├── search-black.png │ │ │ ├── search-white.png │ │ │ ├── shop-black.png │ │ │ ├── shop-white.png │ │ │ ├── star-black.png │ │ │ ├── star-white.png │ │ │ ├── user-black.png │ │ │ ├── user-white.png │ │ │ ├── video-black.png │ │ │ ├── video-white.png │ │ │ ├── arrow-d-black.png │ │ │ ├── arrow-d-white.png │ │ │ ├── arrow-l-black.png │ │ │ ├── arrow-l-white.png │ │ │ ├── arrow-r-black.png │ │ │ ├── arrow-r-white.png │ │ │ ├── arrow-u-black.png │ │ │ ├── arrow-u-white.png │ │ │ ├── bullets-black.png │ │ │ ├── bullets-white.png │ │ │ ├── calendar-black.png │ │ │ ├── calendar-white.png │ │ │ ├── carat-d-black.png │ │ │ ├── carat-d-white.png │ │ │ ├── carat-l-black.png │ │ │ ├── carat-l-white.png │ │ │ ├── carat-r-black.png │ │ │ ├── carat-r-white.png │ │ │ ├── carat-u-black.png │ │ │ ├── carat-u-white.png │ │ │ ├── comment-black.png │ │ │ ├── comment-white.png │ │ │ ├── forward-black.png │ │ │ ├── forward-white.png │ │ │ ├── location-black.png │ │ │ ├── location-white.png │ │ │ ├── recycle-black.png │ │ │ ├── recycle-white.png │ │ │ ├── refresh-black.png │ │ │ ├── refresh-white.png │ │ │ ├── arrow-d-l-black.png │ │ │ ├── arrow-d-l-white.png │ │ │ ├── arrow-d-r-black.png │ │ │ ├── arrow-d-r-white.png │ │ │ ├── arrow-u-l-black.png │ │ │ ├── arrow-u-l-white.png │ │ │ ├── arrow-u-r-black.png │ │ │ ├── arrow-u-r-white.png │ │ │ ├── forbidden-black.png │ │ │ ├── forbidden-white.png │ │ │ ├── navigation-black.png │ │ │ └── navigation-white.png │ │ │ └── icons-svg │ │ │ ├── minus-black.svg │ │ │ ├── navigation-black.svg │ │ │ ├── minus-white.svg │ │ │ ├── mail-black.svg │ │ │ ├── navigation-white.svg │ │ │ ├── back-black.svg │ │ │ ├── check-black.svg │ │ │ ├── star-black.svg │ │ │ ├── forward-black.svg │ │ │ ├── mail-white.svg │ │ │ ├── action-black.svg │ │ │ ├── carat-d-black.svg │ │ │ ├── carat-l-black.svg │ │ │ ├── carat-r-black.svg │ │ │ ├── carat-u-black.svg │ │ │ ├── star-white.svg │ │ │ ├── back-white.svg │ │ │ ├── check-white.svg │ │ │ ├── forward-white.svg │ │ │ ├── action-white.svg │ │ │ ├── carat-d-white.svg │ │ │ ├── carat-l-white.svg │ │ │ ├── carat-r-white.svg │ │ │ ├── carat-u-white.svg │ │ │ ├── heart-black.svg │ │ │ ├── video-black.svg │ │ │ ├── heart-white.svg │ │ │ ├── video-white.svg │ │ │ ├── location-black.svg │ │ │ ├── location-white.svg │ │ │ ├── alert-black.svg │ │ │ ├── alert-white.svg │ │ │ ├── eye-black.svg │ │ │ ├── lock-black.svg │ │ │ ├── eye-white.svg │ │ │ ├── recycle-black.svg │ │ │ ├── lock-white.svg │ │ │ ├── bars-black.svg │ │ │ ├── shop-black.svg │ │ │ ├── recycle-white.svg │ │ │ ├── bars-white.svg │ │ │ ├── cloud-black.svg │ │ │ ├── shop-white.svg │ │ │ ├── cloud-white.svg │ │ │ ├── arrow-d-black.svg │ │ │ ├── arrow-l-black.svg │ │ │ ├── arrow-r-black.svg │ │ │ ├── arrow-u-black.svg │ │ │ ├── search-black.svg │ │ │ ├── arrow-d-white.svg │ │ │ ├── arrow-r-white.svg │ │ │ ├── edit-black.svg │ │ │ ├── arrow-d-l-black.svg │ │ │ ├── arrow-d-r-black.svg │ │ │ ├── arrow-l-white.svg │ │ │ ├── arrow-u-l-black.svg │ │ │ ├── arrow-u-r-black.svg │ │ │ ├── arrow-u-white.svg │ │ │ ├── home-black.svg │ │ │ ├── plus-black.svg │ │ │ ├── search-white.svg │ │ │ ├── arrow-d-l-white.svg │ │ │ ├── arrow-d-r-white.svg │ │ │ ├── arrow-u-l-white.svg │ │ │ ├── arrow-u-r-white.svg │ │ │ ├── delete-black.svg │ │ │ ├── edit-white.svg │ │ │ ├── home-white.svg │ │ │ ├── plus-white.svg │ │ │ ├── delete-white.svg │ │ │ ├── tag-black.svg │ │ │ ├── camera-black.svg │ │ │ ├── tag-white.svg │ │ │ ├── comment-black.svg │ │ │ ├── camera-white.svg │ │ │ ├── comment-white.svg │ │ │ ├── info-black.svg │ │ │ ├── info-white.svg │ │ │ ├── bullets-black.svg │ │ │ ├── bullets-white.svg │ │ │ ├── clock-black.svg │ │ │ ├── clock-white.svg │ │ │ ├── calendar-black.svg │ │ │ ├── calendar-white.svg │ │ │ ├── power-black.svg │ │ │ ├── phone-black.svg │ │ │ ├── power-white.svg │ │ │ ├── refresh-black.svg │ │ │ ├── phone-white.svg │ │ │ ├── refresh-white.svg │ │ │ ├── audio-black.svg │ │ │ ├── audio-white.svg │ │ │ ├── user-black.svg │ │ │ ├── user-white.svg │ │ │ ├── forbidden-black.svg │ │ │ ├── forbidden-white.svg │ │ │ ├── grid-black.svg │ │ │ ├── grid-white.svg │ │ │ ├── gear-black.svg │ │ │ └── gear-white.svg │ │ └── rosworker.js ├── gunicorn_cfg.py ├── _version.py ├── frontend │ ├── __init__.py │ └── flask_views.py ├── __init__.py ├── config_template.py ├── api_0_1 │ ├── __init__.py │ └── index.py ├── api_0_2 │ └── __init__.py ├── context.py └── exceptions.py ├── .gitignore ├── requirements ├── tools.txt ├── tests.txt ├── dev.txt └── ROS │ ├── kinetic.txt │ └── indigo.txt ├── instance └── rostful.cfg ├── .travis.yml ├── tox.ini ├── .pyup.yml ├── setup.py ├── README.rst └── .gitchangelog.rc /.gitmodules: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_rostful/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/test_rostful/test_params.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /doc/readme_link.rst: -------------------------------------------------------------------------------- 1 | .. include:: ../README.rst 2 | -------------------------------------------------------------------------------- /doc/changelog_link.rst: -------------------------------------------------------------------------------- 1 | .. include:: ../CHANGELOG.rst 2 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include requirements.txt 2 | include package.xml 3 | -------------------------------------------------------------------------------- /rostful/templates/security/email/reset_notice.txt: -------------------------------------------------------------------------------- 1 | Your password has been reset -------------------------------------------------------------------------------- /rostful/templates/security/email/reset_notice.html: -------------------------------------------------------------------------------- 1 |

Your password has been reset

-------------------------------------------------------------------------------- /rostful/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/favicon.ico -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.cmake 2 | build/ 3 | bin/ 4 | lib/ 5 | *~ 6 | *.pyc 7 | *.pyo 8 | doc/.zim 9 | *.geany 10 | -------------------------------------------------------------------------------- /requirements/tools.txt: -------------------------------------------------------------------------------- 1 | # for release, version doesnt matter, we always work in virtualenv 2 | gitchangelog 3 | twine -------------------------------------------------------------------------------- /rostful/templates/security/email/reset_instructions.html: -------------------------------------------------------------------------------- 1 |

Click here to reset your password

-------------------------------------------------------------------------------- /rostful/templates/security/email/reset_instructions.txt: -------------------------------------------------------------------------------- 1 | Click the link below to reset your password: 2 | 3 | {{ reset_link }} -------------------------------------------------------------------------------- /rostful/gunicorn_cfg.py: -------------------------------------------------------------------------------- 1 | import multiprocessing 2 | 3 | bind = "127.0.0.1:8080" 4 | workers = multiprocessing.cpu_count() * 2 + 1 5 | -------------------------------------------------------------------------------- /rostful/templates/security/email/confirmation_instructions.txt: -------------------------------------------------------------------------------- 1 | Please confirm your email through the link below: 2 | 3 | {{ confirmation_link }} -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/ajax-loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/ajax-loader.gif -------------------------------------------------------------------------------- /rostful/templates/security/email/login_instructions.txt: -------------------------------------------------------------------------------- 1 | Welcome {{ user.email }}! 2 | 3 | You can log into your through the link below: 4 | 5 | {{ login_link }} -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/eye-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/eye-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/eye-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/eye-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/tag-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/tag-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/tag-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/tag-white.png -------------------------------------------------------------------------------- /requirements/tests.txt: -------------------------------------------------------------------------------- 1 | # latest version to validate behavior on pure python env 2 | pytest==3.5.0 3 | pytest-xdist==1.22.2 # for --boxed 4 | hypothesis==3.56.3 5 | numpy==1.14.2 6 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/action-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/action-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/action-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/action-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/alert-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/alert-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/alert-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/alert-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/audio-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/audio-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/audio-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/audio-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/back-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/back-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/back-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/back-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/bars-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/bars-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/bars-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/bars-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/camera-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/camera-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/camera-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/camera-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/check-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/check-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/check-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/check-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/clock-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/clock-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/clock-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/clock-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/cloud-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/cloud-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/cloud-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/cloud-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/delete-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/delete-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/delete-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/delete-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/edit-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/edit-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/edit-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/edit-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/gear-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/gear-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/gear-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/gear-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/grid-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/grid-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/grid-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/grid-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/heart-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/heart-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/heart-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/heart-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/home-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/home-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/home-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/home-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/info-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/info-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/info-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/info-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/lock-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/lock-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/lock-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/lock-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/mail-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/mail-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/mail-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/mail-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/minus-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/minus-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/minus-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/minus-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/phone-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/phone-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/phone-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/phone-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/plus-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/plus-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/plus-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/plus-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/power-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/power-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/power-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/power-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/search-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/search-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/search-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/search-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/shop-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/shop-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/shop-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/shop-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/star-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/star-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/star-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/star-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/user-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/user-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/user-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/user-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/video-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/video-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/video-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/video-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/arrow-d-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/arrow-d-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/arrow-d-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/arrow-d-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/arrow-l-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/arrow-l-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/arrow-l-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/arrow-l-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/arrow-r-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/arrow-r-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/arrow-r-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/arrow-r-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/arrow-u-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/arrow-u-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/arrow-u-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/arrow-u-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/bullets-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/bullets-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/bullets-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/bullets-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/calendar-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/calendar-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/calendar-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/calendar-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/carat-d-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/carat-d-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/carat-d-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/carat-d-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/carat-l-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/carat-l-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/carat-l-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/carat-l-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/carat-r-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/carat-r-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/carat-r-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/carat-r-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/carat-u-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/carat-u-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/carat-u-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/carat-u-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/comment-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/comment-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/comment-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/comment-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/forward-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/forward-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/forward-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/forward-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/location-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/location-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/location-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/location-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/recycle-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/recycle-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/recycle-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/recycle-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/refresh-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/refresh-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/refresh-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/refresh-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/arrow-d-l-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/arrow-d-l-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/arrow-d-l-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/arrow-d-l-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/arrow-d-r-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/arrow-d-r-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/arrow-d-r-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/arrow-d-r-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/arrow-u-l-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/arrow-u-l-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/arrow-u-l-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/arrow-u-l-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/arrow-u-r-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/arrow-u-r-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/arrow-u-r-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/arrow-u-r-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/forbidden-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/forbidden-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/forbidden-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/forbidden-white.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/navigation-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/navigation-black.png -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-png/navigation-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyros-dev/rostful/HEAD/rostful/static/js/jquery-mobile/images/icons-png/navigation-white.png -------------------------------------------------------------------------------- /rostful/templates/security/email/confirmation_instructions.html: -------------------------------------------------------------------------------- 1 |

Please confirm your email through the link below:

2 | 3 |

Confirm my account

-------------------------------------------------------------------------------- /rostful/templates/security/email/login_instructions.html: -------------------------------------------------------------------------------- 1 |

Welcome {{ user.email }}!

2 | 3 |

You can log into your through the link below:

4 | 5 |

Login now

-------------------------------------------------------------------------------- /rostful/templates/security/email/welcome.txt: -------------------------------------------------------------------------------- 1 | Welcome {{ user.email }}! 2 | 3 | {% if security.confirmable %} 4 | You can confirm your email through the link below: 5 | 6 | {{ confirmation_link }} 7 | {% endif %} -------------------------------------------------------------------------------- /requirements/dev.txt: -------------------------------------------------------------------------------- 1 | # Requirements to get specific development version fo various dependencies 2 | 3 | # -e git+https://github.com/pyros-dev/pyros-common.git#egg=pyros_common 4 | # -e git+https://github.com/pyros-dev/pyros.git@fix_exceptions#egg=pyros 5 | 6 | -------------------------------------------------------------------------------- /rostful/static/js/rosworker.js: -------------------------------------------------------------------------------- 1 | var i = 0; 2 | 3 | function timedCount() { 4 | i = i + 1; 5 | postMessage(i); 6 | setTimeout("timedCount()",500); 7 | } 8 | 9 | //TODO : all kinds of fancy stuff with roslib and rosbridge 10 | 11 | timedCount(); -------------------------------------------------------------------------------- /rostful/templates/security/email/welcome.html: -------------------------------------------------------------------------------- 1 |

Welcome {{ user.email }}!

2 | 3 | {% if security.confirmable %} 4 |

You can confirm your email through the link below:

5 | 6 |

Confirm my account

7 | {% endif %} -------------------------------------------------------------------------------- /rostful/templates/security/email/change_notice.txt: -------------------------------------------------------------------------------- 1 | Your password has been changed 2 | {% if security.recoverable %} 3 | If you did not change your password, click the link below to reset it. 4 | {{ url_for_security('forgot_password', _external=True) }} 5 | {% endif %} 6 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | # This should gather all unit tests for the flask server. 2 | # - using the mock in pyros 3 | # - using the ros interface 4 | # - using other mp systems interface 5 | 6 | # Integration REST API tests will be in each multiprocess system folder 7 | 8 | 9 | -------------------------------------------------------------------------------- /rostful/templates/security/email/change_notice.html: -------------------------------------------------------------------------------- 1 |

Your password has been changed.

2 | {% if security.recoverable %} 3 |

If you did not change your password, click here to reset it.

4 | {% endif %} 5 | -------------------------------------------------------------------------------- /rostful/_version.py: -------------------------------------------------------------------------------- 1 | # Store the version here so: 2 | # 1) we don't load dependencies by storing it in __init__.py 3 | # 2) we can import it in setup.py for the same reason 4 | # 3) we can import it into your module module 5 | __version_info__ = ('0', '2', '1') 6 | __version__ = '.'.join(__version_info__) 7 | -------------------------------------------------------------------------------- /rostful/templates/security/send_login.html: -------------------------------------------------------------------------------- 1 | {% from "security/_macros.html" import render_field_with_errors, render_field %} 2 | {% include "security/_messages.html" %} 3 |

Login

4 |
5 | {{ send_login_form.hidden_tag() }} 6 | {{ render_field_with_errors(send_login_form.email) }} 7 | {{ render_field(send_login_form.submit) }} 8 |
9 | {% include "security/_menu.html" %} -------------------------------------------------------------------------------- /doc/weblinks.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file contains a common collection of web links. Include it 3 | wherever these links are needed. 4 | 5 | It is explicitly excluded in ``conf.py``, because it does not 6 | appear anywhere in the TOC tree. 7 | 8 | .. _ROS: http://wiki.ros.org 9 | .. _Pyros: http://github.com/asmodehn/pyros 10 | .. _REST: https://en.wikipedia.org/wiki/Representational_state_transfer 11 | .. _ROS name: http://wiki.ros.org/Names 12 | 13 | 14 | -------------------------------------------------------------------------------- /rostful/templates/security/forgot_password.html: -------------------------------------------------------------------------------- 1 | {% from "security/_macros.html" import render_field_with_errors, render_field %} 2 | {% include "security/_messages.html" %} 3 |

Send password reset instructions

4 |
5 | {{ forgot_password_form.hidden_tag() }} 6 | {{ render_field_with_errors(forgot_password_form.email) }} 7 | {{ render_field(forgot_password_form.submit) }} 8 |
9 | {% include "security/_menu.html" %} -------------------------------------------------------------------------------- /rostful/templates/security/send_confirmation.html: -------------------------------------------------------------------------------- 1 | {% from "security/_macros.html" import render_field_with_errors, render_field %} 2 | {% include "security/_messages.html" %} 3 |

Resend confirmation instructions

4 |
5 | {{ send_confirmation_form.hidden_tag() }} 6 | {{ render_field_with_errors(send_confirmation_form.email) }} 7 | {{ render_field(send_confirmation_form.submit) }} 8 |
9 | {% include "security/_menu.html" %} -------------------------------------------------------------------------------- /doc/internals.rst: -------------------------------------------------------------------------------- 1 | Internals 2 | ========= 3 | 4 | rostful server 5 | -------------- 6 | 7 | 8 | .. automodule:: rostful.__main__ 9 | :members: 10 | :undoc-members: 11 | :inherited-members: 12 | 13 | .. automodule:: rostful.config 14 | :members: 15 | :undoc-members: 16 | :inherited-members: 17 | 18 | .. automodule:: rostful.flask_views 19 | :members: 20 | :undoc-members: 21 | :inherited-members: 22 | 23 | .. automodule:: rostful.server 24 | :members: 25 | :undoc-members: 26 | :inherited-members: 27 | 28 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/minus-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /rostful/frontend/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import absolute_import 3 | 4 | # Reference for package structure since this is a flask app : http://flask.pocoo.org/docs/0.10/patterns/packages/ 5 | import types 6 | from flask import Blueprint, current_app 7 | import flask_restful 8 | 9 | app_blueprint = Blueprint('main', __name__) 10 | 11 | # importing package content mandatory to setup routes for blueprint 12 | from . import flask_views 13 | 14 | """ 15 | The Package managing api 16 | """ 17 | 18 | __all__ = [ 19 | 'app_blueprint', 20 | 'current_app', 21 | 22 | ] 23 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/navigation-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/minus-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /rostful/templates/security/reset_password.html: -------------------------------------------------------------------------------- 1 | {% from "security/_macros.html" import render_field_with_errors, render_field %} 2 | {% include "security/_messages.html" %} 3 |

Reset password

4 |
5 | {{ reset_password_form.hidden_tag() }} 6 | {{ render_field_with_errors(reset_password_form.password) }} 7 | {{ render_field_with_errors(reset_password_form.password_confirm) }} 8 | {{ render_field(reset_password_form.submit) }} 9 |
10 | {% include "security/_menu.html" %} -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/mail-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/navigation-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/back-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/check-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/star-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/forward-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/mail-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /rostful/templates/security/change_password.html: -------------------------------------------------------------------------------- 1 | {% from "security/_macros.html" import render_field_with_errors, render_field %} 2 | {% include "security/_messages.html" %} 3 |

Change password

4 |
5 | {{ change_password_form.hidden_tag() }} 6 | {{ render_field_with_errors(change_password_form.password) }} 7 | {{ render_field_with_errors(change_password_form.new_password) }} 8 | {{ render_field_with_errors(change_password_form.new_password_confirm) }} 9 | {{ render_field(change_password_form.submit) }} 10 |
11 | 12 | -------------------------------------------------------------------------------- /rostful/templates/security/login_user.html: -------------------------------------------------------------------------------- 1 | {% from "security/_macros.html" import render_field_with_errors, render_field %} 2 | {% include "security/_messages.html" %} 3 |

Login

4 |
5 | {{ login_user_form.hidden_tag() }} 6 | {{ render_field_with_errors(login_user_form.email) }} 7 | {{ render_field_with_errors(login_user_form.password) }} 8 | {{ render_field_with_errors(login_user_form.remember) }} 9 | {{ render_field(login_user_form.next) }} 10 | {{ render_field(login_user_form.submit) }} 11 |
12 | {% include "security/_menu.html" %} -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/action-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/carat-d-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/carat-l-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/carat-r-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/carat-u-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/star-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/back-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/check-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/forward-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/action-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/carat-d-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/carat-l-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/carat-r-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/carat-u-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/heart-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/video-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/heart-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 8 | 9 | -------------------------------------------------------------------------------- /rostful/templates/security/register_user.html: -------------------------------------------------------------------------------- 1 | {% from "security/_macros.html" import render_field_with_errors, render_field %} 2 | {% include "security/_messages.html" %} 3 |

Register

4 |
5 | {{ register_user_form.hidden_tag() }} 6 | {{ render_field_with_errors(register_user_form.email) }} 7 | {{ render_field_with_errors(register_user_form.password) }} 8 | {% if register_user_form.password_confirm %} 9 | {{ render_field_with_errors(register_user_form.password_confirm) }} 10 | {% endif %} 11 | {{ render_field(register_user_form.submit) }} 12 |
13 | {% include "security/_menu.html" %} -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/video-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 8 | 9 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/location-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 8 | 9 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/location-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 8 | 9 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/alert-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 8 | 9 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/alert-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 8 | 9 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/eye-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 8 | 9 | -------------------------------------------------------------------------------- /rostful/templates/error.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {% block title %}{% endblock %} | ROSTful 6 | 7 | 8 | 9 | 10 | 11 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | {{ error }} 21 |
22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/lock-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 8 | 9 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/eye-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 8 | 9 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/recycle-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 8 | 9 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/lock-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/bars-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/shop-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /rostful/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import absolute_import 3 | 4 | from ._version import __version__ 5 | 6 | import os 7 | 8 | # Reference for package structure since this is a flask app : http://flask.pocoo.org/docs/0.10/patterns/packages/ 9 | from .context import set_pyros_client, get_pyros_client 10 | 11 | # HACK for ROS 12 | from .flaskapp import create_app, setup_app_routes 13 | from .exceptions import WrongMessageFormat, ServiceNotFound, ServiceTimeout, NoPyrosClient 14 | 15 | 16 | 17 | ### TODO This package also contains a Client 18 | 19 | __all__ = [ 20 | '__version__', 21 | 'WrongMessageFormat', 22 | 'ServiceNotFound', 23 | 'ServiceTimeout', 24 | 'NoPyrosClient', 25 | 26 | 'create_app', 27 | 'setup_app_routes', 28 | 'set_pyros_client', 29 | 'get_pyros_client', 30 | ] 31 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/recycle-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/bars-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/cloud-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/shop-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /requirements/ROS/kinetic.txt: -------------------------------------------------------------------------------- 1 | # Requirements for running on top of kinetic 2 | 3 | # xenial packages versions to validate behavior with these versions for a potential ROS package for rostful 4 | # pytest==2.8.7 5 | # pytest-xdist==1.8 # for --boxed 6 | # hypothesis==3.0.1 7 | # numpy==1.11.0 8 | # TESTS are outside the package : they dont need to match the system packages on the corresponding ROS DISTRO 9 | # since they willnot be distributed as part of the package. 10 | 11 | # Package Dependencies need to match ROS (or xenial's) package version 12 | 13 | Flask==0.10.1 14 | Flask-Cors==3.0.3 15 | Flask-Restful==0.3.4 16 | Flask-reverse-proxy==0.2.0 17 | click==6.2.0 18 | webargs==1.3.4 19 | pyros==0.4.3 20 | #pyros_setup # pyros should provide this... 21 | #pyros_config # pyros should provide this... 22 | tornado==4.2.1 23 | simplejson==3.8.1 24 | tblib==1.2.0 25 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/cloud-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/arrow-d-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/arrow-l-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/arrow-r-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/arrow-u-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/search-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/arrow-d-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/arrow-r-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/edit-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/arrow-d-l-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/arrow-d-r-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/arrow-l-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/arrow-u-l-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/arrow-u-r-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/arrow-u-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/home-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/plus-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/search-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/arrow-d-l-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/arrow-d-r-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/arrow-u-l-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/arrow-u-r-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/delete-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/edit-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/home-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/plus-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /requirements/ROS/indigo.txt: -------------------------------------------------------------------------------- 1 | # Requirements for running on top of indigo 2 | 3 | # trusty packages versions to validate behavior with these versions for a potential ROS package for rostful 4 | # pytest==2.5.1 5 | # pytest-xdist==1.8 # for --boxed 6 | # hypothesis==3.0.1 # backported to indigo as https://github.com/asmodehn/hypothesis-rosrelease 7 | # numpy>=1.8.1 8 | # TESTS are outside the package : they dont need to match the system packages on the corresponding ROS DISTRO 9 | # since they willnot be distributed as part of the package. 10 | 11 | # Package Dependencies need to match ROS (or trusty's) package version 12 | 13 | Flask==0.10.1 14 | Flask-Cors==3.0.2 15 | Flask-Restful==0.3.4 16 | Flask-reverse-proxy==0.2.0 17 | click==6.2.0 18 | webargs==1.3.4 19 | pyros==0.4.1 20 | #pyros_setup # pyros should provide this... 21 | #pyros_config # pyros should provide this... 22 | tornado==4.2.1 23 | simplejson==3.3.1 24 | tblib==1.2.0 -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/delete-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/tag-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/camera-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/tag-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/comment-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /rostful/config_template.py: -------------------------------------------------------------------------------- 1 | # Default Settings for rostful (flask wsgi app) 2 | # must be solid and ready for prod. 3 | # Dev setting can be set in a dev config file 4 | 5 | DEBUG = False 6 | 7 | # Do not play with this. 8 | # Only useful for subdomains 9 | # SERVER_NAME = "mytest.local:8080" 10 | # To specify where to run the server, use command line args 11 | 12 | # This can be overridden via command line argument --server 13 | SERVER_TYPE = "tornado" 14 | 15 | # Settings to pass to pyros node to interface with ROS 16 | PYROS_TOPICS = [] 17 | PYROS_SERVICES = [] 18 | PYROS_PARAMS = [] 19 | 20 | # Not really safe enough to be enabled by default yet. 21 | PYROS_USE_CONNECTION_CACHE = False 22 | 23 | # Not specifying these means we use pyros default. 24 | # PYROS_CONNECTION_CACHE_LIST_TOPIC = "/rocon/connection_cache/list" 25 | # PYROS_CONNECTION_CACHE_DIFF_TOPIC = "/rocon/connection_cache/diff" 26 | # 27 | # PYROS_SETUP_WORKSPACES 28 | # PYROS_SETUP_DISTRO 29 | -------------------------------------------------------------------------------- /instance/rostful.cfg: -------------------------------------------------------------------------------- 1 | # Default Settings for rostful (flask wsgi app) 2 | # must be solid and ready for prod. 3 | # Dev setting can be set in a dev config file 4 | 5 | DEBUG = True 6 | 7 | # Do not play with this. 8 | # Only useful for subdomains 9 | # SERVER_NAME = "mytest.local:8080" 10 | # To specify where to run the server, use command line args 11 | 12 | # This can be overridden via command line argument --server 13 | SERVER_TYPE = "flask" 14 | 15 | # Settings to pass to pyros node to interface with ROS 16 | # TODO : this should be managed by pyros separately, not here... 17 | PYROS_TOPICS = ['/.*'] 18 | PYROS_SERVICES = ['/.*'] 19 | PYROS_PARAMS = ['/.*'] 20 | 21 | # not assuming cache available by default 22 | PYROS_USE_CONNECTION_CACHE = False 23 | 24 | # Not specifying these means we use pyros default. 25 | # PYROS_CONNECTION_CACHE_LIST_TOPIC = "/rocon/connection_cache/list" 26 | # PYROS_CONNECTION_CACHE_DIFF_TOPIC = "/rocon/connection_cache/diff" 27 | # 28 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/camera-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 10 | 11 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/comment-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/info-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/info-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/bullets-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 10 | 11 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/bullets-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 11 | 12 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/clock-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/clock-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /rostful/api_0_1/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import absolute_import 3 | 4 | # Reference for package structure since this is a flask app : http://flask.pocoo.org/docs/0.10/patterns/packages/ 5 | import types 6 | from flask import Blueprint, current_app 7 | import flask_restful 8 | 9 | api_blueprint = Blueprint('api_0_1', __name__) 10 | 11 | 12 | api = flask_restful.Api(api_blueprint) 13 | 14 | # TODO : check https://github.com/jmcarp/flask-apispec 15 | 16 | # TODO : double check if needed or already in flask-restful 17 | # -> already in flask_restful : resource decorator 18 | # def api_route(self, *args, **kwargs): 19 | # def wrapper(cls): 20 | # self.add_resource(cls, *args, **kwargs) 21 | # return cls 22 | # return wrapper 23 | # 24 | # api.route = types.MethodType(api_route, api) 25 | 26 | # importing package content mandatory to setup routes for blueprint 27 | from . import flask_views 28 | 29 | """ 30 | The Package managing api 31 | """ 32 | 33 | __all__ = [ 34 | 'api_blueprint', 35 | 'api', 36 | 'current_app', 37 | 38 | ] 39 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/calendar-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/calendar-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/power-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 12 | 13 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/phone-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 12 | 13 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/power-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 12 | 13 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/refresh-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/phone-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 12 | 13 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/refresh-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/audio-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/audio-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /rostful/api_0_2/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import absolute_import, print_function 3 | 4 | # Reference for package structure since this is a flask app : http://flask.pocoo.org/docs/0.10/patterns/packages/ 5 | import types 6 | from flask import Blueprint, current_app 7 | import flask_restful 8 | 9 | api_blueprint = Blueprint('api_0_2', __name__) 10 | 11 | 12 | api = flask_restful.Api(api_blueprint) 13 | 14 | 15 | # TODO get rid of flask-restful dependency here (seems no longer maintained), and implement functionality directly with flask. 16 | # Might be just slowto catch up on flask, but better remove it anyway (low benefit for the cost of maintenance) 17 | # Try FlaskAPI... 18 | 19 | # TODO : double check if needed or already in flask-restful 20 | # def api_route(self, *args, **kwargs): 21 | #  def wrapper(cls): 22 | #  self.add_resource(cls, *args, **kwargs) 23 | #  return cls 24 | #  return wrapper 25 | 26 | # api.route = types.MethodType(api_route, api) 27 | 28 | # importing package content mandatory to setup routes for blueprint 29 | #from . import flask_views 30 | 31 | """ 32 | The Package managing api 33 | """ 34 | 35 | __all__ = [ 36 | 'api_blueprint', 37 | 'api', 38 | 'current_app' 39 | ] 40 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/user-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/user-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/forbidden-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/forbidden-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: python 3 | 4 | branches: 5 | except: 6 | - gh-pages 7 | 8 | 9 | env: 10 | # These will be used to determine the proper version of our dependencies 11 | # We will NOT rely on a full ROS installation. 12 | - ROS_DISTRO=indigo 13 | - ROS_DISTRO=kinetic #TOX_PARAMS="--hypothesis-profile travis" 14 | 15 | # to get latest dependencies (not released in a ROS distro yet) 16 | - ROS_DISTRO=latest #TOX_PARAMS="--hypothesis-profile travis" 17 | 18 | python: 19 | - 2.7 20 | # NOT READY FOR PY3 YET... (see pyzmp) 21 | #- 3.4 22 | #- 3.5 23 | #- 3.6 24 | #- pypy 25 | #- pypy3 26 | 27 | # Add specific python3 versions 28 | #matrix: 29 | # include: 30 | # explicitely matching python version to the version on the ubuntu distro supported by the ROS LTS distro 31 | #TODO - python: 3.4 32 | # env: ROS_DISTRO=indigo 33 | #TODO - python: 3.5 34 | # env: ROS_DISTRO=kinetic TOX_PARAMS="--hypothesis-profile travis" 35 | # exclude: 36 | # explicitely exclude python3 version not supported by matching linux distro 37 | #- python: 3.6 38 | # env: ROS_DISTRO=indigo 39 | #- python: 3.6 40 | # env: ROS_DISTRO=kinetic TOX_PARAMS="--hypothesis-profile travis" 41 | 42 | install: 43 | - pip install tox tox-travis 44 | 45 | script: 46 | - tox #-- $TOX_PARAMS 47 | 48 | notifications: 49 | email: false 50 | -------------------------------------------------------------------------------- /rostful/templates/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {% block title %}{% endblock %} | ROSTful 6 | 7 | 8 | 9 | 10 | 11 | 12 | 15 | 16 | 17 | 18 |
19 | {% block UTIL_js %}{% endblock %} 20 |
21 |

{% block header %}{% endblock %}

22 |
23 | 24 |
25 | {% block GET_ajax %}{% endblock %} 26 | {% block GET %}{% endblock %} 27 |
28 | 29 | 30 |
31 | {% block POST_ajax %}{% endblock %} 32 | {% block POST %}{% endblock %} 33 |
34 | 35 |
36 |

{% block footer %}{% endblock %}

37 |
38 | 39 |
40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /rostful/context.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from flask import current_app, g 3 | 4 | from .exceptions import NoPyrosClient 5 | 6 | # TODO : improve that into using app context. 7 | # Creating pyros client should be simple and fast to be created everytime a request arrives. 8 | # Pyros should also be able to support multiple client at the same time... 9 | 10 | def set_pyros_client(app, pyros_client): 11 | app.pyros_client = pyros_client 12 | 13 | 14 | def get_pyros_client(): 15 | """ 16 | Give access to pyros client from app context 17 | :return: 18 | """ 19 | pyros_client = getattr(g, '_pyros_client', None) 20 | if pyros_client is None: 21 | try: 22 | pyros_client = g._pyros_client = current_app.pyros_client # copying the app pyros client from app object to context 23 | except AttributeError as exc: 24 | if not hasattr(current_app, 'pyros_client'): 25 | raise NoPyrosClient("Warning : Pyros Client not found in current app : {0}".format(exc)) 26 | else: 27 | raise 28 | return pyros_client 29 | 30 | 31 | def register_teardown(app): 32 | @app.teardown_appcontext 33 | def teardown_pyros_client(exception): 34 | pyros_client = getattr(g, '_pyros_client', None) 35 | # TODO : cleanup if necessary. 36 | #if pyros_client is not None: 37 | # pyros_client.close() -------------------------------------------------------------------------------- /doc/index.rst: -------------------------------------------------------------------------------- 1 | Rostful 2 | ======= 3 | 4 | This `Python package`_ and `ROS`_ package allows sending `REST`_ request to a multiprocess system supported by `Pyros`_. 5 | 6 | ROS usage 7 | --------- 8 | 9 | Rostful interfaces a `ROS`_ system and the web world through a `REST`_ API. 10 | A `ROS name` :: 11 | 12 | /namespace/node_name/service_name 13 | 14 | is made available via the URL (by default) :: 15 | 16 | http://localhost:8000/ros/namespace/node_name/service_name 17 | 18 | - A service accept a POST request and returns a json message containing the original ROS service response 19 | - A Topic accept a POST on a Subscriber ( and returns nothing ) and a GET on a Publisher (and returns the last message received from that publisher) 20 | - A Param accept GET and POST request to get/set the value. 21 | 22 | Errors: 23 | 24 | - A request that is successful but doesnt return anything ( publisher didn't send any message ) return 204 25 | - A request to an non existent topic or service returns 404 26 | - A request with wrong message format returns 400 27 | - A request that triggers an error in the ROS system returns 500, as well as a traceback, usually very handy for debugging the issue. 28 | - A request that is not replied in 10 seconds returns 504 29 | 30 | 31 | 32 | .. include:: weblinks.rst 33 | 34 | Contents: 35 | 36 | .. toctree:: 37 | :maxdepth: 2 38 | 39 | readme_link 40 | internals 41 | changelog_link 42 | 43 | Indices and tables 44 | ================== 45 | 46 | * :ref:`genindex` 47 | * :ref:`modindex` 48 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/grid-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /rostful/static/js/jquery-mobile/images/icons-svg/grid-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /rostful/templates/param.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block title %}Param {{ param.fullname }}{% endblock %} 3 | {% block header %}Param {{ param.fullname }}{% endblock %} 4 | {% block GET %} 5 | 6 |

Receive message

7 | 10 |

11 | {% endblock %}
12 | 
13 | {% block GET_ajax %}
14 | 
40 | {% endblock %}
41 | 
42 | 
43 | {% from 'macros.html' import content_navbar %}
44 | {% block footer %}{{ content_navbar() }}{% endblock %}
45 | 
46 | 
47 | 


--------------------------------------------------------------------------------
/tests/test_rostful/test_services.py:
--------------------------------------------------------------------------------
 1 | from __future__ import absolute_import
 2 | 
 3 | import sys
 4 | import os
 5 | sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')))
 6 | 
 7 | import mock
 8 | import unittest
 9 | 
10 | import pyros
11 | from rostful import create_app, set_pyros_client, ServiceNotFound
12 | 
13 | 
14 | class TestServicesNoPyros(unittest.TestCase):
15 | 
16 |     @classmethod
17 |     def setUpClass(cls):
18 |         pass
19 | 
20 |     @classmethod
21 |     def tearDownClass(cls):
22 |         pass
23 | 
24 |     def setUp(self):
25 |         app = create_app()
26 |         app.config['TESTING'] = True
27 |         app.testing = True  # required to check for exceptions
28 |         self.client = app.test_client()
29 | 
30 |     def tearDown(self):
31 |         pass
32 | 
33 | 
34 | class TestServicesPyros(TestServicesNoPyros):
35 | 
36 |     @classmethod
37 |     def setUpClass(cls):
38 |         pass
39 | 
40 |     @classmethod
41 |     def tearDownClass(cls):
42 |         pass
43 | 
44 |     # overloading run to instantiate the pyros context manager
45 |     # this will call setup and teardown
46 |     def run(self, result=None):
47 |         # argv is rosargs but these have no effect on client, so no need to pass anything here
48 |         with pyros.pyros_ctx(name='rostful', argv=[], mock_client=True, base_path=os.path.join(os.path.dirname(__file__), '..', '..', '..')) as node_ctx:
49 |             self.node_ctx = node_ctx
50 |             set_pyros_client(self.node_ctx.client)
51 |             super(TestServicesPyros, self).run(result)
52 | 
53 |     def setUp(self):
54 |         super(TestServicesPyros, self).setUp()
55 | 
56 |     def tearDown(self):
57 |         super(TestServicesPyros, self).tearDown()
58 | 
59 | if __name__ == '__main__':
60 | 
61 |     import nose
62 |     nose.runmodule()
63 | 


--------------------------------------------------------------------------------
/tests/test_rostful/test_topics.py:
--------------------------------------------------------------------------------
 1 | from __future__ import absolute_import
 2 | 
 3 | import sys
 4 | import os
 5 | sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..', 'src')))
 6 | 
 7 | import flask
 8 | 
 9 | import unittest
10 | import nose
11 | 
12 | import pyros
13 | from rostful import create_app, set_pyros_client, ServiceNotFound
14 | 
15 | 
16 | class TestTopicsNoPyros(unittest.TestCase):
17 | 
18 |     @classmethod
19 |     def setUpClass(cls):
20 |         pass
21 | 
22 |     @classmethod
23 |     def tearDownClass(cls):
24 |         pass
25 | 
26 |     def setUp(self):
27 |         app = create_app
28 |         app.config['TESTING'] = True
29 |         app.testing = True  # required to check for exceptions
30 |         self.client = app.test_client()
31 | 
32 |     def tearDown(self):
33 |         pass
34 | 
35 | 
36 | class TestTopicsPyros(TestTopicsNoPyros):
37 | 
38 |     @classmethod
39 |     def setUpClass(cls):
40 |         pass
41 | 
42 |     @classmethod
43 |     def tearDownClass(cls):
44 |         pass
45 | 
46 |     # overloading run to instantiate the pyros context manager
47 |     # this will call setup and teardown
48 |     def run(self, result=None):
49 |         # argv is rosargs but these have no effect on client, so no need to pass anything here
50 |         with pyros.pyros_ctx(name='rostful', argv=[], mock_client=True, base_path=os.path.join(os.path.dirname(__file__), '..', '..', '..')) as node_ctx:
51 |             self.node_ctx = node_ctx
52 |             set_pyros_client(self.node_ctx.client)
53 |             super(TestTopicsPyros, self).run(result)
54 | 
55 |     def setUp(self):
56 |         super(TestTopicsPyros, self).setUp()
57 | 
58 |     def tearDown(self):
59 |         super(TestTopicsPyros, self).tearDown()
60 | 
61 | 
62 | if __name__ == '__main__':
63 | 
64 |     import nose
65 |     nose.runmodule()


--------------------------------------------------------------------------------
/tox.ini:
--------------------------------------------------------------------------------
 1 | # tox.ini , put in same dir as setup.py
 2 | [tox]
 3 | 
 4 | skip_missing_interpreters=True
 5 | 
 6 | envlist =
 7 |   # based on ros distro with python2 base
 8 |   py27-{indigo,kinetic,latest},
 9 | 
10 |   # Proper py3 version for LTS releases
11 |   #py34-indigo,
12 |   #py35-kinetic,
13 | 
14 |   # based on ros distro with python3 base
15 |   #py36-{latest}
16 | 
17 | #, pypy
18 | #, pypy3
19 | 
20 | [travis]
21 | python =
22 |   # we test every current ROS1 distro on python 2.7 (official python support for ROS1)
23 |   2.7 : py27
24 |   # specific old python supported natively on ubuntu/ROS LTS distro
25 |   #3.4 : py34
26 |   #3.5 : py35
27 |   # we test every current ROS1 distro on latest python (to ensure support from latest python)
28 |   #3.6 : py36
29 | 
30 | # not tested yet
31 | #pypy = pypy
32 | #pypy3 = pypy3
33 | 
34 | # We depend on travis matrix
35 | [travis:env]
36 | ROS_DISTRO =
37 |   kinetic: kinetic
38 |   indigo: indigo
39 |   latest: latest
40 | 
41 | [testenv]
42 | 
43 | setenv =
44 |     # prevent tox to create a bunch of useless bytecode files in tests/
45 |     PYTHONDONTWRITEBYTECODE=1
46 | 
47 | # Dependencies matching the version in each ROS distro
48 | deps =
49 | 
50 |     indigo: -rrequirements/ROS/indigo.txt
51 |     indigo: -rrequirements/tests.txt
52 |     indigo: -rrequirements/dev.txt
53 | 
54 |     kinetic: -rrequirements/ROS/kinetic.txt
55 |     kinetic: -rrequirements/tests.txt
56 |     kinetic: -rrequirements/dev.txt
57 | 
58 |     latest: -rrequirements/tests.txt
59 |     latest: -rrequirements/dev.txt
60 | 
61 | # to always force recreation and avoid unexpected side effects
62 | recreate=True
63 | 
64 | changedir = tests
65 | 
66 | commands=
67 |     # we want to make sure python finds the installed package in tox env
68 |     # and doesn't confuse with pyc generated during dev (which happens if we use self test feature here)
69 |     python -m pytest --basetemp={envtmpdir} test_rostful {posargs}
70 |     # Note : -s here might break your terminal...
71 | 


--------------------------------------------------------------------------------
/tests/test_rostful/test_frontend.py:
--------------------------------------------------------------------------------
 1 | # This should test that a frontend is provided
 2 | # Testing the UI is probably out of scope for this test.
 3 | # Might also be unsuitable if the UI changes often...
 4 | 
 5 | from __future__ import absolute_import
 6 | 
 7 | import sys
 8 | import os
 9 | sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')))
10 | 
11 | import mock
12 | import unittest
13 | 
14 | import pyros
15 | from rostful import create_app, set_pyros_client, ServiceNotFound
16 | 
17 | 
18 | class TestFrontendNoPyros(unittest.TestCase):
19 | 
20 |     @classmethod
21 |     def setUpClass(cls):
22 |         pass
23 | 
24 |     @classmethod
25 |     def tearDownClass(cls):
26 |         pass
27 | 
28 |     def setUp(self):
29 |         app = create_app()
30 |         app.config['TESTING'] = True
31 |         app.testing = True  # required to check for exceptions
32 |         self.client = app.test_client()
33 | 
34 |     def tearDown(self):
35 |         pass
36 | 
37 | 
38 | class TestFrontendPyros(TestFrontendNoPyros):
39 | 
40 |     @classmethod
41 |     def setUpClass(cls):
42 |         pass
43 | 
44 |     @classmethod
45 |     def tearDownClass(cls):
46 |         pass
47 | 
48 |     # overloading run to instantiate the pyros context manager
49 |     # this will call setup and teardown
50 |     def run(self, result=None):
51 |         # argv is rosargs but these have no effect on client, so no need to pass anything here
52 |         with pyros.pyros_ctx(name='rostful', argv=[], mock_client=True, base_path=os.path.join(os.path.dirname(__file__), '..', '..', '..')) as node_ctx:
53 |             self.node_ctx = node_ctx
54 |             set_pyros_client(self.node_ctx.client)
55 |             super(TestFrontendPyros, self).run(result)
56 | 
57 |     def setUp(self):
58 |         super(TestFrontendPyros, self).setUp()
59 | 
60 |     def tearDown(self):
61 |         super(TestFrontendPyros, self).tearDown()
62 | 
63 | if __name__ == '__main__':
64 | 
65 |     import nose
66 |     nose.runmodule()
67 | 


--------------------------------------------------------------------------------
/rostful/api_0_1/index.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | from __future__ import absolute_import
 3 | 
 4 | import importlib
 5 | import json
 6 | import base64
 7 | from flask import jsonify, url_for
 8 | 
 9 | import flask_restful as restful
10 | 
11 | 
12 | from webargs.flaskparser import FlaskParser, use_kwargs
13 | from webargs import fields
14 | 
15 | from . import api, current_app
16 | 
17 | parser = FlaskParser()
18 | 
19 | """
20 | Flask View Dealing with URLs
21 | """
22 | 
23 | 
24 | @api.route('/', strict_slashes=False)
25 | class Index(restful.Resource):  # TODO : unit test that stuff !!! http://flask.pocoo.org/docs/0.10/testing/
26 | 
27 |     """
28 |     This is used especially to handle errors in this blueprint (REST style : JSON response)
29 |     """
30 |     def get(self):
31 | 
32 |         """Print available url and matching endpoints."""
33 |         routes = {}
34 |         for rule in current_app.url_map.iter_rules():
35 |             try:
36 |                 if rule.endpoint != 'static':
37 |                     if hasattr(current_app.view_functions[rule.endpoint], 'import_name'):
38 |                         import_name = current_app.view_functions[rule.endpoint].import_name
39 |                         obj = importlib.import_module(import_name)
40 |                     else:
41 |                         obj = current_app.view_functions[rule.endpoint]
42 | 
43 |                     routes[rule.rule] = {
44 |                         "methods": ','.join(rule.methods),
45 |                         "endpoint": rule.endpoint,
46 |                         "description": obj.__doc__
47 |                     }
48 | 
49 |             except Exception as exc:
50 |                 routes[rule.rule] = {
51 |                         "methods": ','.join(rule.methods),
52 |                         "endpoint": rule.endpoint,
53 |                         "description": "INVALID ROUTE DEFINITION!!!"
54 |                 }
55 |                 route_info = "%s => %s" % (rule.rule, rule.endpoint)
56 |                 current_app.logger.error("Invalid route: %s" % route_info, exc_info=True)
57 | 
58 |         return jsonify(routes)
59 | 
60 | 


--------------------------------------------------------------------------------
/.pyup.yml:
--------------------------------------------------------------------------------
 1 | # configure updates globally
 2 | # default: all
 3 | # allowed: all, insecure, False
 4 | update: all
 5 | 
 6 | # configure dependency pinning globally
 7 | # default: True
 8 | # allowed: True, False
 9 | pin: True
10 | 
11 | # set the default branch
12 | # default: empty, the default branch on GitHub
13 | branch: master
14 | 
15 | # update schedule
16 | # default: empty
17 | # allowed: "every day", "every week", ..
18 | schedule: "every week"
19 | 
20 | # search for requirement files
21 | # default: True
22 | # allowed: True, False
23 | search: False
24 | 
25 | # Specify requirement files by hand, default is empty
26 | # default: empty
27 | # allowed: list
28 | requirements:
29 |   # These need to be manually pinned to match ROS distros versions
30 |   - requirements/ROS/indigo.txt:
31 |       # don't update dependencies, don't try to auto pin
32 |       update: False
33 |       pin: False
34 |   - requirements/ROS/kinetic.txt:
35 |       # don't update dependencies, don't try to auto pin
36 |       update: False
37 |       pin: False
38 | 
39 |   - requirements/dev.txt:
40 |       # update all dependencies, use global 'pin' default
41 |       update: all
42 | 
43 |   - requirements/tests.txt:
44 |       # update all dependencies, use global 'pin' default
45 |       update: all
46 | 
47 |   - requirements/tools.txt:
48 |       # update all dependencies,  never pin (dev will use whatever is latest for them)
49 |       update: all
50 |       pin: False
51 | 
52 | 
53 | # TODO : review tests nd default values after ROS things are out of the python repo
54 | 
55 | # add a label to pull requests, default is not set
56 | # requires private repo permissions, even on public repos
57 | # default: empty
58 | label_prs: update
59 | 
60 | # assign users to pull requests, default is not set
61 | # requires private repo permissions, even on public repos
62 | # default: empty
63 | assignees:
64 |  - asmodehn
65 | 
66 | # configure the branch prefix the bot is using
67 | # default: pyup-
68 | branch_prefix: pyup/
69 | 
70 | # set a global prefix for PRs
71 | # default: empty
72 | #pr_prefix: "Bug #12345"
73 | 
74 | # allow to close stale PRs
75 | # default: True
76 | #close_prs: True


--------------------------------------------------------------------------------
/rostful/exceptions.py:
--------------------------------------------------------------------------------
 1 | # -*- coding: utf-8 -*-
 2 | from __future__ import absolute_import
 3 | 
 4 | # EXCEPTION CLASSES
 5 | # should be used to return anything that is not 2xx, python style.
 6 | 
 7 | 
 8 | class NoPyrosClient(Exception):
 9 |     status_code = 500
10 | 
11 |     def __init__(self, message, status_code=None, traceback=None):
12 |         Exception.__init__(self)
13 |         self.message = message
14 |         if status_code is not None:
15 |             self.status_code = status_code
16 |         self.traceback = traceback
17 | 
18 |     def to_dict(self):
19 |         rv = dict({})
20 |         rv['message'] = self.message
21 |         rv['traceback'] = self.traceback
22 |         return rv
23 | 
24 | 
25 | class WrongMessageFormat(Exception):
26 |     status_code = 400
27 | 
28 |     def __init__(self, message, status_code=None, traceback=None):
29 |         Exception.__init__(self)
30 |         self.message = message
31 |         if status_code is not None:
32 |             self.status_code = status_code
33 |         self.traceback = traceback
34 | 
35 |     def to_dict(self):
36 |         rv = dict({})
37 |         rv['message'] = self.message
38 |         rv['traceback'] = self.traceback
39 |         return rv
40 | 
41 | 
42 | class ServiceTimeout(Exception):
43 |     status_code = 504
44 | 
45 |     def __init__(self, message, status_code=None, traceback=None):
46 |         Exception.__init__(self)
47 |         self.message = message
48 |         if status_code is not None:
49 |             self.status_code = status_code
50 |         self.traceback = traceback
51 | 
52 |     def to_dict(self):
53 |         rv = dict({})
54 |         rv['message'] = self.message
55 |         rv['traceback'] = self.traceback
56 |         return rv
57 | 
58 | 
59 | class ServiceNotFound(Exception):
60 |     status_code = 404
61 | 
62 |     def __init__(self, message, status_code=None, traceback=None):
63 |         Exception.__init__(self)
64 |         self.message = message
65 |         if status_code is not None:
66 |             self.status_code = status_code
67 |         self.traceback = traceback
68 | 
69 |     def to_dict(self):
70 |         rv = dict({})
71 |         rv['message'] = self.message
72 |         rv['traceback'] = self.traceback
73 |         return rv
74 | 


--------------------------------------------------------------------------------
/rostful/static/js/jquery-mobile/images/icons-svg/gear-black.svg:
--------------------------------------------------------------------------------
 1 | 
 2 | 
 3 | 
 4 | 
 6 | 
22 | 
23 | 
24 | 
25 | 
26 | 
27 | 
28 | 
29 | 
30 | 
31 | 
32 | 
33 | 
34 | 
35 | 
36 | 
37 | 
38 | 
39 | 
40 | 
41 | 
42 | 
43 | 
44 | 
45 | 
46 | 
47 | 
48 | 
49 | 
50 | 
51 | 
52 | 
53 | 


--------------------------------------------------------------------------------
/rostful/static/js/jquery-mobile/images/icons-svg/gear-white.svg:
--------------------------------------------------------------------------------
 1 | 
 2 | 
 3 | 
 4 | 
 6 | 
22 | 
23 | 
24 | 
25 | 
26 | 
27 | 
28 | 
29 | 
30 | 
31 | 
32 | 
33 | 
34 | 
35 | 
36 | 
37 | 
38 | 
39 | 
40 | 
41 | 
42 | 
43 | 
44 | 
45 | 
46 | 
47 | 
48 | 
49 | 
50 | 
51 | 
52 | 
53 | 


--------------------------------------------------------------------------------
/rostful/templates/service.html:
--------------------------------------------------------------------------------
 1 | {% extends "layout.html" %}
 2 | {% block title %}Service {{ service.fullname }}{% endblock %}
 3 | {% block header %}Service {{ service.fullname }}{% endblock %}
 4 | 
 5 | {% block GET %}
 6 | 
 7 | {% endblock %}
 8 | 
 9 | {% block GET_ajax %}
10 | 
11 | {% endblock %}
12 | 
13 | {% from 'macros.html' import generate_inputs, generate_msgdata, dynamic_array_input %}
14 | 
15 | {% block UTIL_js %}
16 | 
21 | {% endblock %}
22 | 
23 | {% block POST %}
24 |   

Send message

25 | 26 | 27 | 28 |
29 | {{ generate_inputs(service.srvtype[0]) }} 30 | 31 |
32 |

33 |   

34 | 
35 | {% endblock %}
36 | 
37 | {% block POST_ajax %}
38 | 
71 | {% endblock %}
72 | 
73 | 
74 | {% from 'macros.html' import content_navbar %}
75 | {% block footer %}{{ content_navbar() }}{% endblock %}
76 | 
77 | 
78 | 


--------------------------------------------------------------------------------
/rostful/templates/index.html:
--------------------------------------------------------------------------------
  1 | 
  2 | 
  3 | 
  4 | 
  5 | ROSTful - ROS REST interface
  6 | 
  7 | 
  8 | 
  9 | 
 10 | 
 11 | 
 12 | 
 15 | 
 16 | 
 17 | 
 18 | 
 19 | {% from 'macros.html' import navbar %}
 20 | 
 21 | {% if services %}
 22 | 
23 |
24 |

Services

25 |
26 | {% for name, service in services.iteritems() %} 27 | {{ service.fullname }} 28 | {% endfor%} 29 |
30 | {{ navbar(services, topics, params, 'services') }} 31 |
32 |
33 | {% endif%} 34 | 35 | {% if topics %} 36 |
37 |
38 |

Topics

39 |
40 | {% for name, topic in topics.iteritems() %} 41 | {{ topic.fullname }} 42 | {% endfor%} 43 |
44 | {{ navbar(services, topics, params, 'topics') }} 45 |
46 |
47 | {% endif%} 48 | 49 | {% if params %} 50 |
51 |
52 |

Params

53 |
54 | {% for name, param in params.iteritems() %} 55 | {{ param.fullname }} 56 | {% endfor%} 57 |
58 | {{ navbar(services, topics, params, 'params') }} 59 |
60 |
61 | {% endif%} 62 | 63 | 100 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /doc/tutorial.rst: -------------------------------------------------------------------------------- 1 | ================================================ 2 | Rostful Tutorial 1 : Chatter - the roslaunch way 3 | ================================================ 4 | 5 | ******* 6 | Install 7 | ******* 8 | 9 | Create workspace for rostful testing:: 10 | 11 | mkdir -p rostful_ws/src 12 | cd rostful_ws/src 13 | 14 | You can manage your workspace as usual with wstool (optional):: 15 | 16 | wstool init 17 | wstool set rostful ... 18 | wstool set pyros ... 19 | 20 | Install dependencies:: 21 | 22 | rosdep install --from-path src --ignore-src -y 23 | 24 | **Is there a Problem ?** 25 | 26 | - Currently tornado might not be installed and the debian package from trusty is too old. 27 | you need tornado > 4.0, so on trusty you should install it from pip:: 28 | 29 | sudo apt-get install pip 30 | sudo pip install tornado 31 | 32 | 33 | ***** 34 | Build 35 | ***** 36 | 37 | Build the workspace as usual with catkin:: 38 | 39 | source /opt/ros/indigo/setup.bash 40 | catkin_make 41 | 42 | **Is there a Problem ?** 43 | 44 | *** 45 | Run 46 | *** 47 | 48 | Start roscore in one terminal:: 49 | 50 | source /opt/ros/indigo/setup.bash 51 | roscore & 52 | 53 | Start a talker node in another terminal:: 54 | 55 | source /opt/ros/indigo/setup.bash 56 | rosrun roscpp_tutorials talker 57 | 58 | 59 | Start rostful in a third terminal:: 60 | 61 | source devel/setup.bash 62 | roslaunch rostful rostful.launch 63 | 64 | 65 | To understand what is happening, it is always good to have a look at your system. 66 | Here are a few commands useful to inspect:: 67 | 68 | yujin@lenovo:~/rostful_ws$ rosnode list 69 | /rosout 70 | /rostful 71 | /talker 72 | 73 | yujin@lenovo:~/rostful_ws$ ps aux | grep rostful 74 | yujin 6617 1.0 0.2 287180 21620 pts/9 Sl+ 12:40 0:00 /usr/bin/python /opt/ros/indigo/bin/roslaunch rostful rostful.launch 75 | yujin 6635 0.0 0.0 23636 3512 ? Ss 12:40 0:00 /bin/bash /home/yujin/rostful_ws/src/rostful/scripts/devserver -p 8080 -s flask ~connections_list:=/rocon/connection_cache/list ~connections_diff:=/rocon/connection_cache/diff __name:=rostful __log:=/home/yujin/.ros/log/f8e4d7c4-4a3a-11e6-810e-5c514fba7886/rostful-1.log 76 | yujin 6639 1.0 0.5 159696 41840 ? S 12:40 0:00 python -tt -m rostful run -p 8080 -s flask --ros-arg=~connections_list:=/rocon/connection_cache/list --ros-arg=~connections_diff:=/rocon/connection_cache/diff --ros-arg=__name:=rostful --ros-arg=__log:=/home/yujin/.ros/log/f8e4d7c4-4a3a-11e6-810e-5c514fba7886/rostful-1.log 77 | 78 | yujin@lenovo:~/rostful_ws$ pstree -cap 6617 79 | roslaunch,6617 /opt/ros/indigo/bin/roslaunch rostful rostful.launch 80 | ├─devserver,6635 /home/yujin/rostful_ws/src/rostful/scripts/devserver -p 8080 -s flask... 81 | │ └─python,6639 -tt -m rostful run -p 8080 -s flask ... 82 | │ ├─python,6642 -tt -m rostful run -p 8080 -s flask ... 83 | │ │ ├─{python},6690 84 | │ │ └─{python},6718 85 | │ ├─python,6661 -tt -m rostful run -p 8080 -s flask ... 86 | │ └─python,6688 -tt -m rostful run -p 8080 -s flask ... 87 | │ ├─{python},6704 88 | │ ├─{python},6705 89 | │ ├─{python},6708 90 | │ ├─{python},6716 91 | │ ├─{python},6717 92 | │ └─{python},6720 93 | ├─{roslaunch},6624 94 | └─{roslaunch},6625 95 | 96 | 97 | yujin@lenovo:~/rostful_ws$ rostopic list 98 | /chatter 99 | /rosout 100 | /rosout_agg 101 | 102 | 103 | Change rostful Config and Restart:: 104 | 105 | 106 | 107 | Open your browser http://localhost:8080, you should see the Chatter topic 108 | 109 | 110 | **Is there a Problem ?** 111 | 112 | - If you don't see anything on the webpage, there is probably a mistake in the configuration. 113 | Luckily you can pass a regular expression, so change rostful config like so, and restart:: 114 | 115 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /rostful/templates/topic.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block title %}Topic {{ topic.fullname }}{% endblock %} 3 | {% block header %}Topic {{ topic.fullname }}{% endblock %} 4 | {% block GET %} 5 | 6 |

Receive message

7 | 10 |

 11 | {% endblock %}
 12 | 
 13 | {% block GET_ajax %}
 14 | 
 40 | {% endblock %}
 41 | 
 42 | 
 43 | {% from 'macros.html' import generate_inputs, generate_msgdata %}
 44 | 
 45 | {% block POST %}
 46 |   

Send message

47 | 48 | 49 | 50 |
51 | {{ generate_inputs(topic.msgtype) }} 52 | 53 |
54 |

 55 |   

 56 | 
 57 | {% endblock %}
 58 | 
 59 | {% block POST_ajax %}
 60 | 
 94 | {% endblock %}
 95 | 
 96 | 
 97 | {% from 'macros.html' import content_navbar %}
 98 | {% block footer %}{{ content_navbar() }}{% endblock %}
 99 | 
100 | 
101 | 


--------------------------------------------------------------------------------
/tests/test_rostful/test_app.py:
--------------------------------------------------------------------------------
  1 | from __future__ import absolute_import
  2 | 
  3 | import mock
  4 | import sys
  5 | import os
  6 | 
  7 | #sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', 'rostful')))
  8 | 
  9 | import unittest
 10 | import nose
 11 | 
 12 | from pyros.server.ctx_server import pyros_ctx
 13 | 
 14 | 
 15 | from rostful import create_app, set_pyros_client, ServiceNotFound, NoPyrosClient
 16 | 
 17 | 
 18 | # Basic Test class for an simple Flask wsgi app
 19 | class TestAppNoPyros(unittest.TestCase):
 20 | 
 21 |     @classmethod
 22 |     def setUpClass(cls):
 23 |         pass
 24 | 
 25 |     @classmethod
 26 |     def tearDownClass(cls):
 27 |         pass
 28 | 
 29 |     def setUp(self):
 30 |         # forcing dev config to not rely on the complex ROS/python/flask path mess,
 31 |         # tests can be started in all kinds of weird ways (nose auto import, etc.)
 32 |         #config_path = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), 'instance', 'rostful.cfg')
 33 |         #self.app = create_app(configfile_override=config_path)
 34 |         # TESTS needs to work for BOTH installed and source package -> we have to rely on flask instance configuration mechanism...
 35 |         self.app = create_app()
 36 |         self.app.debug = True
 37 |         self.app.config['TESTING'] = True
 38 |         self.app.testing = True  # required to check for exceptions
 39 | 
 40 |     def tearDown(self):
 41 |         pass
 42 | 
 43 |     def test_index_root(self):
 44 |         with self.app.test_client() as client:
 45 |             res = client.get('/', follow_redirects=True)
 46 |             nose.tools.assert_equals(res.status_code, 200)
 47 | 
 48 |     def test_frontend_root(self):
 49 |         with self.app.test_client() as client:
 50 |             res = client.get('/frontend')
 51 |             nose.tools.assert_equals(res.status_code, 200)
 52 | 
 53 |     def test_crossdomain(self):
 54 |         with self.app.test_client() as client:
 55 |             res = client.get('/', follow_redirects=True)
 56 |             nose.tools.assert_equals(res.status_code, 200)
 57 |             # Not working. TODO : recheck after switching to WSGI Cors
 58 |             #nose.tools.assert_equals(res.headers['Access-Control-Allow-Origin'], '*')
 59 |             #nose.tools.assert_equals(res.headers['Access-Control-Max-Age'], '21600')
 60 |             #nose.tools.assert_true('HEAD' in res.headers['Access-Control-Allow-Methods'])
 61 |             #nose.tools.assert_true('OPTIONS' in res.headers['Access-Control-Allow-Methods'])
 62 |             #nose.tools.assert_true('GET' in res.headers['Access-Control-Allow-Methods'])
 63 | 
 64 |     def test_error(self):
 65 |          with self.app.test_client() as client:
 66 |             res = client.get('/api/v0.1/non-existent')
 67 |             # TODO : dig into flask restful to find out how we should handle custom errors http://flask-restful-cn.readthedocs.io/en/0.3.4/extending.html
 68 |             nose.tools.assert_equal(res.status_code, 404)
 69 | 
 70 | 
 71 | class TestAppPyros(TestAppNoPyros):
 72 | 
 73 |     @classmethod
 74 |     def setUpClass(cls):
 75 |         pass
 76 | 
 77 |     @classmethod
 78 |     def tearDownClass(cls):
 79 |         pass
 80 | 
 81 |     # overloading run to instantiate the pyros context manager
 82 |     # this will call setup and teardown
 83 |     def run(self, result=None):
 84 |         # argv is rosargs but these have no effect on client, so no need to pass anything here
 85 |         with pyros_ctx(name='rostful', argv=[], mock_client=True) as node_ctx:
 86 |             self.node_ctx = node_ctx
 87 |             super(TestAppPyros, self).run(result)
 88 | 
 89 |     def setUp(self):
 90 |         super(TestAppPyros, self).setUp()
 91 |         set_pyros_client(self.app, self.node_ctx.client)
 92 | 
 93 |     def tearDown(self):
 94 |         super(TestAppPyros, self).tearDown()
 95 | 
 96 |     def test_index_root(self):
 97 |         super(TestAppPyros, self).test_index_root()
 98 |         # verify pyros mock client was actually called
 99 |         self.node_ctx.client.topics.assert_called_once_with()
100 |         self.node_ctx.client.services.assert_called_once_with()
101 |         self.node_ctx.client.params.assert_called_once_with()
102 | 
103 |     def test_crossdomain(self):
104 |         super(TestAppPyros, self).test_crossdomain()
105 |         # verify pyros mock client was actually called
106 |         self.node_ctx.client.topics.assert_called_once_with()
107 |         self.node_ctx.client.services.assert_called_once_with()
108 |         self.node_ctx.client.params.assert_called_once_with()
109 | 
110 |     def test_error(self):
111 |         with self.app.test_client() as client:
112 |             res = client.get('/api/v0.1/non-existent')
113 |             nose.tools.assert_equal(res.status_code, 404)
114 |             # TODO : dig into flask restful to find out how we should handle custom errors http://flask-restful-cn.readthedocs.io/en/0.3.4/extending.html
115 |         # verify pyros mock client was actually called
116 |         # self.node_ctx.client.topics.assert_called_once_with()
117 |         # self.node_ctx.client.services.assert_called_once_with()
118 |         # This is not implemented yet
119 |         #self.node_ctx.client.params.assert_called_once_with()
120 | 
121 | 
122 | if __name__ == '__main__':
123 | 
124 |     import nose
125 |     nose.runmodule()
126 | 


--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
  1 | import setuptools
  2 | import subprocess
  3 | 
  4 | # using setuptools : http://pythonhosted.org/setuptools/
  5 | 
  6 | with open('rostful/_version.py') as vf:
  7 |     exec(vf.read())
  8 | 
  9 | 
 10 | # Best Flow :
 11 | # Clean previous build & dist
 12 | # $ gitchangelog >CHANGELOG.rst
 13 | # change version in code and changelog
 14 | # $ python setup.py prepare_release
 15 | # WAIT FOR TRAVIS CHECKS
 16 | # $ python setup.py publish
 17 | # => TODO : try to do a simpler "release" command
 18 | 
 19 | #
 20 | # And then for ROS, directly (tag is already in git repo):
 21 | # bloom-release --rosdistro kinetic --track kinetic pyros_interfaces_ros
 22 | 
 23 | 
 24 | # Clean way to add a custom "python setup.py "
 25 | # Ref setup.py command extension : https://blog.niteoweb.com/setuptools-run-custom-code-in-setup-py/
 26 | class PrepareReleaseCommand(setuptools.Command):
 27 |     """Command to release this package to Pypi"""
 28 |     description = "prepare a release of pyros"
 29 |     user_options = []
 30 | 
 31 |     def initialize_options(self):
 32 |         """init options"""
 33 |         pass
 34 | 
 35 |     def finalize_options(self):
 36 |         """finalize options"""
 37 |         pass
 38 | 
 39 |     def run(self):
 40 |         """runner"""
 41 | 
 42 |         # TODO :
 43 |         # $ gitchangelog >CHANGELOG.rst
 44 |         # change version in code and changelog
 45 |         subprocess.check_call("git commit CHANGELOG.rst rostful/_version.py -m 'v{0}'".format(__version__), shell=True)
 46 |         subprocess.check_call("git push", shell=True)
 47 | 
 48 |         print("You should verify travis checks, and you can publish this release with :")
 49 |         print("  python setup.py publish")
 50 |         sys.exit()
 51 | 
 52 | 
 53 | # Clean way to add a custom "python setup.py "
 54 | # Ref setup.py command extension : https://blog.niteoweb.com/setuptools-run-custom-code-in-setup-py/
 55 | class PublishCommand(setuptools.Command):
 56 |     """Command to release this package to Pypi"""
 57 |     description = "releases pyros to Pypi"
 58 |     user_options = []
 59 | 
 60 |     def initialize_options(self):
 61 |         """init options"""
 62 |         # TODO : register option
 63 |         pass
 64 | 
 65 |     def finalize_options(self):
 66 |         """finalize options"""
 67 |         pass
 68 | 
 69 |     def run(self):
 70 |         """runner"""
 71 |         # TODO : clean build/ and dist/ before building...
 72 |         subprocess.check_call("python setup.py sdist", shell=True)
 73 |         subprocess.check_call("python setup.py bdist_wheel", shell=True)
 74 |         # OLD way:
 75 |         # os.system("python setup.py sdist bdist_wheel upload")
 76 |         # NEW way:
 77 |         # Ref: https://packaging.python.org/distributing/
 78 |         subprocess.check_call("twine upload dist/*", shell=True)
 79 | 
 80 |         subprocess.check_call("git tag -a {0} -m 'version {0}'".format(__version__), shell=True)
 81 |         subprocess.check_call("git push --tags", shell=True)
 82 |         sys.exit()
 83 | 
 84 | 
 85 | 
 86 | # https://hynek.me/articles/conditional-python-dependencies/
 87 | import sys
 88 | sys_requires = []
 89 | if sys.version_info[0:3] <= (2, 7, 9) or (3, 0) < sys.version_info[0:2] <= (3, 4):
 90 |     sys_requires += ['backports.ssl-match-hostname']
 91 | 
 92 | 
 93 | setuptools.setup(
 94 |     name='rostful',
 95 |     version=__version__,
 96 |     description='REST API for ROS',
 97 |     url='http://github.com/asmodehn/rostful',
 98 |     author='AlexV',
 99 |     author_email='asmodehn@gmail.com',
100 |     license='BSD',
101 |     packages=[
102 |         'rostful',
103 |         'rostful.api_0_1',
104 |         'rostful.api_0_2',
105 |         'rostful.frontend',
106 |         #'rostful.tests',  # not embedding tests in package for now...
107 |     ],
108 |     package_dir={
109 |     },
110 |     entry_points={
111 |         'console_scripts': [
112 |             'rostful = rostful.__main__:cli'
113 |         ]
114 |     },
115 |     # this is better than using package data ( since behavior is a bit different from distutils... )
116 |     include_package_data=True,  # use MANIFEST.in during install.
117 |     package_data={  # TODO : might be better to do this in MANIFEST
118 |         'rostful': [
119 |             'static/favicon.ico',
120 |             'static/js/moment/*',
121 |             'static/js/jquery/*',
122 |             'static/js/jquery-mobile/jquery.*',
123 |             'static/js/jquery-mobile/images/ajax-loader.gif',
124 |             'static/js/jquery-mobile/images/icons-png/*',
125 |             'static/js/jquery-mobile/images/icons-svg/*',
126 |             'templates/*.html',
127 |             'templates/security/*.html',
128 |             'templates/security/email/*',
129 |         ],
130 |     },
131 |     install_requires=sys_requires + [
132 |         #'futures>=3.0.2',
133 |         'Flask>=0.10.1',
134 |         'Flask-Cors>=3.0.2',
135 |         'Flask-Restful>=0.3.4',
136 |         'Flask-reverse-proxy',
137 |         'click>=6.2.0',
138 |         'webargs>=1.3.4',
139 |         'pyros>=0.4.3',
140 |         #'pyros_setup>=0.1.5',  # pyros should provide this...
141 |         #'pyros_config>=0.1.4',  # pyros should provide this...
142 |         'tornado>=4.2.1, <5.0',  # untested with tornado > 5.0
143 |         'simplejson',
144 |         'tblib>=1.2',
145 |     ],
146 |     cmdclass={
147 |         'prepare_release': PrepareReleaseCommand,
148 |         'publish': PublishCommand,
149 |     },
150 |     zip_safe=False,  # TODO testing...
151 | )
152 | 
153 | 


--------------------------------------------------------------------------------
/README.rst:
--------------------------------------------------------------------------------
  1 | |Build Status| |Documentation Status| |Updates| |Python 3|
  2 | 
  3 | ROSTful
  4 | =======
  5 | 
  6 | ROStful - A REST API for ROS.
  7 | 
  8 | We follow a `feature branching workflow `_
  9 | 
 10 | Rostful is intended to be the outside layer of ROS (and eventualy any multiprocess system). Meaning it will interface ROS with other systems, over the internet, via HTTP and through a REST API.
 11 | As such, this should be used as any python program, from a virtual environment. We also need to install the specific pyros interface for the system we want to expose.
 12 | 
 13 | ```
 14 | $ mkvirtualenv rostful
 15 | (rostful)$ pip install rostful pyros[ros]
 16 | (rostful)$ python -m rostful flask
 17 | ```
 18 | 
 19 | A ROS package is provided as a third party release, for ease of deployment within a ROS system.
 20 | However it is heavily recommended to do development the "python way", dynamically, using virtual environments, with quick iterations.
 21 | The rostful PyPI package is released more often than the ROS package, and will have latest updates available for use.
 22 | 
 23 | 
 24 | PYTHON VIRTUALENV SETUP
 25 | =======================
 26 | 
 27 | How to setup your python virtual environment on Ubuntu (tested on Xenial 16.04)
 28 | * Install and Setup virtualenvwrapper if needed
 29 | ```
 30 | sudo apt install virtualenvwrapper
 31 | ```
 32 | * Create your virtual environment for your project
 33 | ```
 34 | $ mkvirtualenv myproject
 35 | ```
 36 | * Populate it to use rostful. The catkin dependency is temporarily needed to be able to use the setup.py currently provided in rostful.
 37 | ```
 38 | (myproject)$ pip install rostful pyros[ros]
 39 | (myproject)$ pip install rostful
 40 | ```
 41 | 
 42 | 
 43 | Try it now
 44 | ----------
 45 | 
 46 | Go check the `examples`_
 47 | 
 48 |  Overview
 49 | ---------
 50 | 
 51 | ROStful is a lightweight web server for making ROS services, topics, and
 52 | actions available as RESTful web services.
 53 | 
 54 | ROStful web services primarily use the `rosbridge`_ JSON mapping for ROS
 55 | messages. However, binary serialized ROS messages can be used to
 56 | increase performance.
 57 | 
 58 | The purpose of ROStful is different from `rosbridge`_: rosbridge
 59 | provides an API for ROS through JSON using web sockets. ROStful allows
 60 | specific services, topics, and actions to be provided as web services
 61 | (using plain get and post requests) without exposing underlying ROS
 62 | concepts. The ROStful client, however, additionally provides a modicum
 63 | of multi-master functionality. The client proxy is a node that connects
 64 | to a ROStful web service and exposes the services, topics, and actions
 65 | locally over ROS.
 66 | 
 67 | The ROStful server has no dependencies on 3rd party libraries, and is
 68 | WSGI-compatible and can therefore be used with most web servers like
 69 | Apache and IIS.
 70 | 
 71 |  ROStful web services
 72 | ~~~~~~~~~~~~~~~~~~~~~
 73 | 
 74 | A ROStful web service is a web service that uses ROS data structures for
 75 | input and output. These include services, topics, and actions.
 76 | 
 77 | Service methods accept as input a ROS message over HTTP POST and return
 78 | a ROS message in the response. The input and output cannot be defined
 79 | directly with ROS messages; it must use a ROS service definition.
 80 | 
 81 | Methods denoted as topics may use any ROS message, but are limited to
 82 | accepting that message via HTTP POST or returning it, taking no input,
 83 | via HTTP GET. Topic methods do not need to allow both methods. A topic
 84 | method allowing POST is described as a “subscribing” method, and one
 85 | that allows GET is a “publishing” method.
 86 | 
 87 | Methods denoted as actions consist of a set of subsidiary topic methods,
 88 | the subscribing-only ``goal`` and ``cancel`` methods, and the
 89 | publishing-only ``status``, ``result``, and ``feedback`` methods. These
 90 | methods are located at the url ``/``, where
 91 | the suffix is the subsidiary method name.
 92 | 
 93 | The ROStful server
 94 | ~~~~~~~~~~~~~~~~~~
 95 | 
 96 | The ROStful server can provide services, topics, and actions that are
 97 | locally available over ROS as ROStful web services. Topics may be
 98 | specified as publishing, subscribing, or both.
 99 | 
100 | ROStful uses the rosbridge JSON mapping by default, but binary
101 | serialized ROS messages can be sent with the ``Content-Header`` set to
102 | ``application/vnd.ros.msg``. Giving this MIME type in the ``Accept``
103 | header for queries without input (i.e., publishing topic methods) will
104 | cause the server to return serialized messages.
105 | 
106 | 
107 | 
108 | What will not be in Rostful
109 | ===========================
110 |  - Security related stuff ( Authentication/Authorization ) implementation.
111 |  We will not provide here any Authentication/Authorization mechanisms without ROS providing one first.
112 |  And even after that, the implications of such an implementation would probably fit better in another specific microservice, that we would rely on in rostful.
113 | 
114 | 
115 | 
116 | .. _examples: https://github.com/asmodehn/rostful-examples
117 | .. _rosbridge: http://wiki.ros.org/rosbridge_suite
118 | 
119 | .. |Build Status| image:: https://travis-ci.org/asmodehn/rostful.svg?branch=master
120 |    :target: https://travis-ci.org/asmodehn/rostful
121 |    :alt: Build Status
122 | 
123 | .. |Documentation Status| image:: https://readthedocs.org/projects/rostful/badge/?version=latest
124 |    :target: http://rostful.readthedocs.io/en/latest/?badge=latest
125 |    :alt: Documentation Status
126 | 
127 | .. |Updates| image:: https://pyup.io/repos/github/asmodehn/rostful/shield.svg
128 |     :target: https://pyup.io/repos/github/asmodehn/rostful/
129 |     :alt: Updates
130 | 
131 | .. |Python 3| image:: https://pyup.io/repos/github/asmodehn/rostful/python-3-shield.svg
132 |      :target: https://pyup.io/repos/github/asmodehn/rostful/
133 |      :alt: Python 3
134 | 


--------------------------------------------------------------------------------
/rostful/frontend/flask_views.py:
--------------------------------------------------------------------------------
  1 | # -*- coding: utf-8 -*-
  2 | from __future__ import absolute_import
  3 | 
  4 | import re
  5 | 
  6 | # Reference for package structure since this is a flask app : http://flask.pocoo.org/docs/0.10/patterns/packages/
  7 | from rostful import get_pyros_client
  8 | 
  9 | import time
 10 | 
 11 | from pyros.client.client import PyrosServiceTimeout
 12 | 
 13 | CONFIG_PATH = '_rosdef'
 14 | SRV_PATH = '_srv'
 15 | MSG_PATH = '_msg'
 16 | 
 17 | 
 18 | def get_suffix(path):
 19 |     suffixes = '|'.join([re.escape(s) for s in [CONFIG_PATH, SRV_PATH, MSG_PATH]])
 20 |     match = re.search(r'/(%s)$' % suffixes, path)
 21 |     return match.group(1) if match else ''
 22 | 
 23 | # TODO : remove ROS usage here, keep this a pure Flask App as much as possible
 24 | 
 25 | 
 26 | ROS_MSG_MIMETYPE = 'application/vnd.ros.msg'
 27 | def ROS_MSG_MIMETYPE_WITH_TYPE(rostype):
 28 |     if isinstance(rostype, type):
 29 |         name = rostype.__name__
 30 |         module = rostype.__module__.split('.')[0]
 31 |         rostype = module + '/' + name
 32 |     return 'application/vnd.ros.msg; type=%s' % rostype
 33 | 
 34 | 
 35 | #req should be a flask request
 36 | #TODO : improve package design...
 37 | def request_wants_ros(req):
 38 |     best = req.accept_mimetypes.best_match([ROS_MSG_MIMETYPE,'application/json'])
 39 |     return best == ROS_MSG_MIMETYPE and req.accept_mimetypes[best] > req.accept_mimetypes['application/json']
 40 | #implementation ref : http://flask.pocoo.org/snippets/45/
 41 | 
 42 | 
 43 | def get_json_bool(b):
 44 |     if b:
 45 |         return 'true'
 46 |     else:
 47 |         return 'false'
 48 | 
 49 | 
 50 | def get_query_bool(query_string, param_name):
 51 |     return re.search(r'(^|&)%s((=(true|1))|&|$)' % param_name, query_string, re.IGNORECASE)
 52 | 
 53 | 
 54 | from flask import Flask, request, make_response, render_template, jsonify, redirect
 55 | from flask.views import MethodView
 56 | from flask_restful import reqparse
 57 | import flask_restful as restful
 58 | 
 59 | from . import app_blueprint, current_app
 60 | 
 61 | 
 62 | from webargs.flaskparser import FlaskParser, use_kwargs
 63 | 
 64 | parser = FlaskParser()
 65 | 
 66 | import urllib
 67 | from pyros.client.client import PyrosException
 68 | from rostful.exceptions import ServiceNotFound, ServiceTimeout, WrongMessageFormat, NoPyrosClient
 69 | 
 70 | 
 71 | 
 72 | class Timeout(object):
 73 |     """
 74 |     Small useful timeout class
 75 |     """
 76 |     def __init__(self, seconds):
 77 |         self.seconds = seconds
 78 | 
 79 |     def __enter__(self):
 80 |         self.die_after = time.time() + self.seconds
 81 |         return self
 82 | 
 83 |     def __exit__(self, type, value, traceback):
 84 |         pass
 85 | 
 86 |     @property
 87 |     def timed_out(self):
 88 |         return time.time() > self.die_after
 89 | 
 90 | 
 91 | """
 92 | View for frontend pages
 93 | """
 94 | # TODO: maybe consider http://www.flaskapi.org/
 95 | # TODO: or maybe better https://github.com/OAI/OpenAPI-Specification
 96 | # TODO: or probably best : https://github.com/rantav/flask-restful-swagger
 97 | 
 98 | # TODO : maybe this can remove the need for a separate blueprint all together...
 99 | # http://flask.pocoo.org/snippets/45/
100 | # https://flask-restful.readthedocs.io/en/0.3.2/extending.html#content-negotiation
101 | 
102 | 
103 | @app_blueprint.route('/', strict_slashes=False, endpoint='ros_list')
104 | def ros_list():
105 |     current_app.logger.debug('in ros_list ')
106 | 
107 |     try:
108 |         node_client = get_pyros_client()  # we retrieve pyros client from app context
109 |         return render_template(
110 |                 'index.html',
111 |                 pathname2url=urllib.pathname2url,
112 |                 topics=node_client.topics(),
113 |                 services=node_client.services(),
114 |                 params=node_client.params(),
115 |             )
116 |     except NoPyrosClient as exc:
117 |         # silently handle the case when we dont have pyros running
118 |         return render_template(
119 |             'index.html',
120 |             pathname2url=urllib.pathname2url,
121 |             topics=[],
122 |             services=[],
123 |             params=[],
124 |         )
125 |     except Exception as exc:
126 |         # TODO : properly display exception (debug mode at least, currently "localhost didn’t send any data. ERR_EMPTY_RESPONSE")
127 |         # failing request if unknown exception triggered
128 |         raise
129 | 
130 | 
131 | @app_blueprint.route('/', strict_slashes=False, endpoint='ros_interface')
132 | def ros_interface(rosname):
133 |     current_app.logger.debug('in ros_interface with rosname: %r', rosname)
134 | 
135 |     node_client = get_pyros_client()  # we retrieve pyros client from app context
136 | 
137 |     # we might need to add "/" to rosname passed as url to match absolute service/topics names listed
138 |     if not rosname.startswith("/"):
139 |         rosname = "/" + rosname
140 | 
141 |     services = None
142 |     topics = None
143 |     params = None
144 |     with Timeout(30) as t:
145 |         while not t.timed_out and (services is None or topics is None or params is None):
146 |             try:
147 |                 params = node_client.params()
148 |             except PyrosServiceTimeout:
149 |                 params = None
150 |             try:
151 |                 services = node_client.services()
152 |             except PyrosServiceTimeout:
153 |                 services = None
154 |             try:
155 |                 topics = node_client.topics()
156 |             except PyrosServiceTimeout:
157 |                 topics = None
158 | 
159 |     if t.timed_out:
160 |         raise ServiceNotFound("Cannot list services, topics or params. No response from pyros.")
161 | 
162 |     if rosname in services:
163 |         mode = 'service'
164 |         service = services[rosname]
165 |         return render_template('service.html', service=service)
166 |     elif rosname in topics:
167 |         mode = 'topic'
168 |         topic = topics[rosname]
169 |         return render_template('topic.html', topic=topic)
170 |     elif rosname in params:
171 |         mode = 'param'
172 |         param = params[rosname]
173 |         return render_template('param.html', param=param)
174 |     else:
175 |         raise ServiceNotFound("{0} not found among Pyros exposed services, topics and params".format(rosname))
176 | 
177 | 


--------------------------------------------------------------------------------
/.gitchangelog.rc:
--------------------------------------------------------------------------------
  1 | ##
  2 | ## Format
  3 | ##
  4 | ##   ACTION: [AUDIENCE:] COMMIT_MSG [!TAG ...]
  5 | ##
  6 | ## Description
  7 | ##
  8 | ##   ACTION is one of 'chg', 'fix', 'new'
  9 | ##
 10 | ##       Is WHAT the change is about.
 11 | ##
 12 | ##       'chg' is for refactor, small improvement, cosmetic changes...
 13 | ##       'fix' is for bug fixes
 14 | ##       'new' is for new features, big improvement
 15 | ##
 16 | ##   AUDIENCE is optional and one of 'dev', 'usr', 'pkg', 'test', 'doc'
 17 | ##
 18 | ##       Is WHO is concerned by the change.
 19 | ##
 20 | ##       'dev'  is for developpers (API changes, refactors...)
 21 | ##       'usr'  is for final users (UI changes)
 22 | ##       'pkg'  is for packagers   (packaging changes)
 23 | ##       'test' is for testers     (test only related changes)
 24 | ##       'doc'  is for doc guys    (doc only changes)
 25 | ##
 26 | ##   COMMIT_MSG is ... well ... the commit message itself.
 27 | ##
 28 | ##   TAGs are additionnal adjective as 'refactor' 'minor' 'cosmetic'
 29 | ##
 30 | ##       They are preceded with a '!' or a '@' (prefer the former, as the
 31 | ##       latter is wrongly interpreted in github.) Commonly used tags are:
 32 | ##
 33 | ##       'refactor' is obviously for refactoring code only
 34 | ##       'minor' is for a very meaningless change (a typo, adding a comment)
 35 | ##       'cosmetic' is for cosmetic driven change (re-indentation, 80-col...)
 36 | ##       'wip' is for partial functionality but complete subfunctionality.
 37 | ##
 38 | ## Example:
 39 | ##
 40 | ##   new: usr: support of bazaar implemented
 41 | ##   chg: re-indentend some lines !cosmetic
 42 | ##   new: dev: updated code to be compatible with last version of killer lib.
 43 | ##   fix: pkg: updated year of licence coverage.
 44 | ##   new: test: added a bunch of test around user usability of feature X.
 45 | ##   fix: typo in spelling my name in comment. !minor
 46 | ##
 47 | ##   Please note that multi-line commit message are supported, and only the
 48 | ##   first line will be considered as the "summary" of the commit message. So
 49 | ##   tags, and other rules only applies to the summary.  The body of the commit
 50 | ##   message will be displayed in the changelog without reformatting.
 51 | 
 52 | 
 53 | ##
 54 | ## ``ignore_regexps`` is a line of regexps
 55 | ##
 56 | ## Any commit having its full commit message matching any regexp listed here
 57 | ## will be ignored and won't be reported in the changelog.
 58 | ##
 59 | ignore_regexps = [
 60 |         r'@minor', r'!minor',
 61 |         r'@cosmetic', r'!cosmetic',
 62 |         r'@refactor', r'!refactor',
 63 |         r'@wip', r'!wip',
 64 |         r'^([cC]hg|[fF]ix|[nN]ew)\s*:\s*[p|P]kg:',
 65 |         r'^([cC]hg|[fF]ix|[nN]ew)\s*:\s*[d|D]ev:',
 66 |         r'^(.{3,3}\s*:)?\s*[fF]irst commit.?\s*$',
 67 |   ]
 68 | 
 69 | 
 70 | ## ``section_regexps`` is a list of 2-tuples associating a string label and a
 71 | ## list of regexp
 72 | ##
 73 | ## Commit messages will be classified in sections thanks to this. Section
 74 | ## titles are the label, and a commit is classified under this section if any
 75 | ## of the regexps associated is matching.
 76 | ##
 77 | section_regexps = [
 78 |     ('New', [
 79 | 	r'^[nN]ew\s*:\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n]*)$',
 80 |      ]),
 81 |     ('Changes', [
 82 |         r'^[cC]hg\s*:\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n]*)$',
 83 |      ]),
 84 |     ('Fix', [
 85 |         r'^[fF]ix\s*:\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n]*)$',
 86 |      ]),
 87 | 
 88 |     ('Other', None ## Match all lines
 89 |      ),
 90 | 
 91 | ]
 92 | 
 93 | 
 94 | ## ``body_process`` is a callable
 95 | ##
 96 | ## This callable will be given the original body and result will
 97 | ## be used in the changelog.
 98 | ##
 99 | ## Available constructs are:
100 | ##
101 | ##   - any python callable that take one txt argument and return txt argument.
102 | ##
103 | ##   - ReSub(pattern, replacement): will apply regexp substitution.
104 | ##
105 | ##   - Indent(chars="  "): will indent the text with the prefix
106 | ##     Please remember that template engines gets also to modify the text and
107 | ##     will usually indent themselves the text if needed.
108 | ##
109 | ##   - Wrap(regexp=r"\n\n"): re-wrap text in separate paragraph to fill 80-Columns
110 | ##
111 | ##   - noop: do nothing
112 | ##
113 | ##   - ucfirst: ensure the first letter is uppercase.
114 | ##     (usually used in the ``subject_process`` pipeline)
115 | ##
116 | ##   - final_dot: ensure text finishes with a dot
117 | ##     (usually used in the ``subject_process`` pipeline)
118 | ##
119 | ##   - strip: remove any spaces before or after the content of the string
120 | ##
121 | ## Additionally, you can `pipe` the provided filters, for instance:
122 | #body_process = Wrap(regexp=r'\n(?=\w+\s*:)') | Indent(chars="  ")
123 | #body_process = Wrap(regexp=r'\n(?=\w+\s*:)')
124 | #body_process = noop
125 | body_process = ReSub(r'((^|\n)[A-Z]\w+(-\w+)*: .*(\n\s+.*)*)+$', r'') | strip
126 | 
127 | 
128 | ## ``subject_process`` is a callable
129 | ##
130 | ## This callable will be given the original subject and result will
131 | ## be used in the changelog.
132 | ##
133 | ## Available constructs are those listed in ``body_process`` doc.
134 | subject_process = (strip |
135 |     ReSub(r'^([cC]hg|[fF]ix|[nN]ew)\s*:\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n@]*)(@[a-z]+\s+)*$', r'\4') |
136 |     ucfirst | final_dot)
137 | 
138 | 
139 | ## ``tag_filter_regexp`` is a regexp
140 | ##
141 | ## Tags that will be used for the changelog must match this regexp.
142 | ##
143 | tag_filter_regexp = r'^[0-9]+\.[0-9]+(\.[0-9]+)?$'
144 | 
145 | 
146 | ## ``unreleased_version_label`` is a string
147 | ##
148 | ## This label will be used as the changelog Title of the last set of changes
149 | ## between last valid tag and HEAD if any.
150 | unreleased_version_label = "%%version%% (unreleased)"
151 | 
152 | 
153 | ## ``output_engine`` is a callable
154 | ##
155 | ## This will change the output format of the generated changelog file
156 | ##
157 | ## Available choices are:
158 | ##
159 | ##   - rest_py
160 | ##
161 | ##        Legacy pure python engine, outputs ReSTructured text.
162 | ##        This is the default.
163 | ##
164 | ##   - mustache()
165 | ##
166 | ##        Template name could be any of the available templates in
167 | ##        ``templates/mustache/*.tpl``.
168 | ##        Requires python package ``pystache``.
169 | ##        Examples:
170 | ##           - mustache("markdown")
171 | ##           - mustache("restructuredtext")
172 | ##
173 | ##   - makotemplate()
174 | ##
175 | ##        Template name could be any of the available templates in
176 | ##        ``templates/mako/*.tpl``.
177 | ##        Requires python package ``mako``.
178 | ##        Examples:
179 | ##           - makotemplate("restructuredtext")
180 | ##
181 | output_engine = rest_py
182 | #output_engine = mustache("restructuredtext")
183 | #output_engine = mustache("markdown")
184 | #output_engine = makotemplate("restructuredtext")
185 | 
186 | 
187 | ## ``include_merge`` is a boolean
188 | ##
189 | ## This option tells git-log whether to include merge commits in the log.
190 | ## The default is to include them.
191 | include_merge = False
192 | 


--------------------------------------------------------------------------------