In general, store, pass around and manipulate rocon uri’s as strings. Create rocon_uri.uri.RoconURI objects only as needed when you need to identify individual elements of the uri or or you need to do comparisons. This is a convention generally followed by urllib as well and is easiest in practice.
To create/validate a rocon uri object, simply pass in the rocon uri string(s) to the parser and access via the specialised descriptors:
try:
rocon_uri_object = rocon_uri.parse('rocon:/turtlebot2|pr2/dude/hydro/precise#rocon_apps/chirp')
print rocon_uri_object.hardware_platform.list # output: ['turtlebot2', 'pr2']
print rocon_uri_object.hardware_platform.string # output: 'turtlebot2|pr2'
print rocon_uri_object.name.string # output: 'dude'
print rocon_uri_object.application_framework.string # output: 'hydro'
print rocon_uri_object.operating_system.string # output: 'precise'
print rocon_uri_object.rapp # output: 'rocon_apps/chirp'
except rocon_uri.RoconURIValueError as e:
print("Invalid rocon uri string [%s]" % str(e))
Note the calls to the hardware_platform field via the list and string accessors. This is the same for any of the primary fields stored by a RoconURI object
The fragment part (rapp) does not follow the same rule and can be more simply accessed directly as shown.
Compatibility between two rocon uri strings is often used to determine if an application is runnable on a particular platform, or to compare whether a particular resource (e.g. robot) is able to satisfy a resource request from a rocon service:
try:
rocon_uri_string_a = 'rocon:/turtlebot2/dude/hydro/precise'
rocon_uri_string_b = 'rocon:/turtlebot2/*/hydro/precise'
compatible = rocon_uri.is_compatible(rocon_uri_string_a, rocon_uri_string_b)
except rocon_uri.RoconURIValueError as e:
print("Invalid rocon uri string(s) passed [%s]" % str(e))
There is a rocon_uri command line tool which can help introspect rocon uri strings while offline.:
> rocon_uri help
Utility for introspecting on rocon uri strings.
Commands:
rocon_uri parse URI parse and attempt to validate a rocon URI.
rocon_uri fields print a full list of permitted fields in a rocon uri string.
rocon_uri rules print a full list of the ebnf rules for a rocon uri string.
A more complete list of examples which may be useful to refer to can be found in the exhaustive list of unit test cases:
#!/usr/bin/env python
#
# License: BSD
# https://raw.github.com/robotics-in-concert/rocon_tools/license/LICENSE
#
##############################################################################
# Imports
##############################################################################
# enable some python3 compatibility options:
# (unicode_literals not compatible with python2 uuid module)
from __future__ import absolute_import, print_function
from nose.tools import assert_raises
import rocon_uri
import rocon_console.console as console
##############################################################################
# Tests
##############################################################################
# def test_experiments():
# print(console.bold + "\n****************************************************************************************" + console.reset)
# print(console.bold + "* Experiments" + console.reset)
# print(console.bold + "****************************************************************************************" + console.reset)
# rocon_uri_string = 'rocon://'
# rocon_uri_string = 'rocon:/turtlebot2/dude/hydro/precise#rocon_apps/chirp'
# rocon_uri_object = rocon_uri.parse(rocon_uri_string)
# print("Rocon URI Object: %s" % rocon_uri_object)
# rocon_uri_object2 = rocon_uri.parse('rocon:/turtlebot2|waiterbot/dude/hydro/precise#rocon_apps/chirp')
# print("Rocon URI Object: %s" % str(rocon_uri_object.hardware_platform))
# print("Rocon URI Object : %s" % rocon_uri_object.hardware_platform.string)
# print("Rocon URI Object : %s" % rocon_uri_object.hardware_platform.list)
# print("Rocon URI Object2: %s" % rocon_uri_object2.hardware_platform.string)
# print("Rocon URI Object2: %s" % rocon_uri_object2.hardware_platform.list)
def test_invalid_elements():
print(console.bold + "\n****************************************************************************************" + console.reset)
print(console.bold + "* Raising on invalid elements" + console.reset)
print(console.bold + "****************************************************************************************" + console.reset)
rocon_uri_string = 'rocon:/turtlebot2/dude/hydro/precise#rocon_apps/chirp'
# rocon_uri_string = 'rocon:/turtlebot2/dude/hydro/precise#rocon_apps/chirp' # the empty hier-part also works
invalid_schema = rocon_uri_string.replace('rocon', 'http')
print(console.cyan + " - %s" % invalid_schema + console.reset)
assert_raises(rocon_uri.RoconURIValueError, rocon_uri.parse, invalid_schema)
invalid_hardware_platform = rocon_uri_string.replace('turtlebot2', 'foobar')
print(console.cyan + " - %s" % invalid_hardware_platform + console.reset)
assert_raises(rocon_uri.RoconURIValueError, rocon_uri.parse, invalid_hardware_platform)
invalid_application_framework = rocon_uri_string.replace('hydro', 'dont_box_me_in')
print(console.cyan + " - %s" % invalid_application_framework + console.reset)
assert_raises(rocon_uri.RoconURIValueError, rocon_uri.parse, invalid_application_framework)
invalid_operating_system = rocon_uri_string.replace('precise', 'bados')
print(console.cyan + " - %s" % invalid_operating_system + console.reset)
assert_raises(rocon_uri.RoconURIValueError, rocon_uri.parse, invalid_operating_system)
def test_stringify():
print(console.bold + "\n****************************************************************************************" + console.reset)
print(console.bold + "* String representation" + console.reset)
print(console.bold + "****************************************************************************************" + console.reset)
rocon_uri_string = 'rocon:/turtlebot2/dude/hydro/precise#rocon_apps/chirp'
print(console.cyan + " - %s" % rocon_uri_string + console.reset)
rocon_uri_object = rocon_uri.parse(rocon_uri_string)
assert str(rocon_uri_object) == rocon_uri_string
def test_multiple_elements():
'''
Test the OR functionality.
'''
print(console.bold + "\n****************************************************************************************" + console.reset)
print(console.bold + "* Parsing multiple elements" + console.reset)
print(console.bold + "****************************************************************************************" + console.reset)
rocon_uri_string = 'rocon:/turtlebot2/dude/hydro/precise#rocon_apps/chirp'
multiple_hardware_platforms = rocon_uri_string.replace('turtlebot2', 'turtlebot2|pr2|waiterbot')
print(console.cyan + " - %s" % multiple_hardware_platforms + console.reset)
rocon_uri_object = rocon_uri.parse(multiple_hardware_platforms)
print(console.yellow + " - %s" % rocon_uri_object.hardware_platform.list + console.reset)
assert len(rocon_uri_object.hardware_platform.list) == 3
multiple_operating_systems = rocon_uri_string.replace('precise', 'quantal|precise')
print(console.cyan + " - %s" % multiple_operating_systems + console.reset)
rocon_uri_object = rocon_uri.parse(multiple_operating_systems)
print(console.yellow + " - %s" % rocon_uri_object.operating_system.list + console.reset)
assert len(rocon_uri_object.operating_system.list) == 2
multiple_application_frameworks = rocon_uri_string.replace('hydro', 'hydro|application_framework_other')
print(console.cyan + " - %s" % multiple_application_frameworks + console.reset)
rocon_uri_object = rocon_uri.parse(multiple_application_frameworks)
print(console.yellow + " - %s" % rocon_uri_object.application_framework.list + console.reset)
assert len(rocon_uri_object.application_framework.list) == 2
def test_wildcards():
print(console.bold + "\n****************************************************************************************" + console.reset)
print(console.bold + "* Wildcards" + console.reset)
print(console.bold + "****************************************************************************************" + console.reset)
rocon_uri_string = 'rocon:/turtlebot2/dude/hydro/precise#rocon_apps/chirp'
hardware_platform_uri = rocon_uri_string.replace('turtlebot2', '*')
print(console.cyan + " - %s" % hardware_platform_uri + console.reset)
rocon_uri_object = rocon_uri.parse(hardware_platform_uri)
assert rocon_uri_object.hardware_platform.string == '*'
operating_systems_uri = rocon_uri_string.replace('precise', '*')
print(console.cyan + " - %s" % operating_systems_uri + console.reset)
rocon_uri_object = rocon_uri.parse(operating_systems_uri)
assert rocon_uri_object.operating_system.string == '*'
application_framework_uri = rocon_uri_string.replace('hydro', '*')
print(console.cyan + " - %s" % application_framework_uri + console.reset)
rocon_uri_object = rocon_uri.parse(application_framework_uri)
assert rocon_uri_object.application_framework.string == '*'
name_uri = rocon_uri_string.replace('dude', '*')
print(console.cyan + " - %s" % name_uri + console.reset)
rocon_uri_object = rocon_uri.parse(name_uri)
assert rocon_uri_object.name.string == '*'
def test_missing_fields():
print(console.bold + "\n****************************************************************************************" + console.reset)
print(console.bold + "* Missing Fields" + console.reset)
print(console.bold + "****************************************************************************************" + console.reset)
rocon_uri_string = 'rocon:/turtlebot2/dude/hydro/precise'
no_operating_system = 'rocon:/turtlebot2/dude/hydro'
rocon_uri_object = rocon_uri.parse(no_operating_system)
print(console.cyan + " - %s -> %s" % (no_operating_system, rocon_uri_object) + console.reset)
assert(rocon_uri_object.operating_system.list[0] == '*')
no_application_framework = 'rocon:/turtlebot2/dude'
rocon_uri_object = rocon_uri.parse(no_application_framework)
print(console.cyan + " - %s -> %s" % (no_application_framework, rocon_uri_object) + console.reset)
assert(rocon_uri_object.application_framework.list[0] == '*')
no_name = 'rocon:/turtlebot2'
rocon_uri_object = rocon_uri.parse(no_name)
print(console.cyan + " - %s -> %s" % (no_name, rocon_uri_object) + console.reset)
assert(rocon_uri_object.name.list[0] == '*')
def test_compatibility():
print(console.bold + "\n****************************************************************************************" + console.reset)
print(console.bold + "* Compatibility" + console.reset)
print(console.bold + "****************************************************************************************" + console.reset)
rocon_uri_string = 'rocon:/turtlebot2/dude/hydro/precise'
print(console.cyan + " - %s ~ %s" % (rocon_uri_string, rocon_uri_string) + console.reset)
assert(rocon_uri.is_compatible(rocon_uri_string, rocon_uri_string) == True)
# Missing operating system
modified_rocon_uri_string = 'rocon:/turtlebot2/dude/hydro'
print(console.cyan + " - %s ~ %s" % (rocon_uri_string, modified_rocon_uri_string) + console.reset)
assert(rocon_uri.is_compatible(rocon_uri_string, modified_rocon_uri_string) == True)
# Missing application_framework/operating system
modified_rocon_uri_string = 'rocon:/turtlebot2/dude'
print(console.cyan + " - %s ~ %s" % (rocon_uri_string, modified_rocon_uri_string) + console.reset)
assert(rocon_uri.is_compatible(rocon_uri_string, modified_rocon_uri_string) == True)
# Missing everything
modified_rocon_uri_string = 'rocon:/'
print(console.cyan + " - %s ~ %s" % (rocon_uri_string, modified_rocon_uri_string) + console.reset)
assert(rocon_uri.is_compatible(rocon_uri_string, modified_rocon_uri_string) == True)
# Wildcards
modified_rocon_uri_string = 'rocon:/*/*/*/*'
print(console.cyan + " - %s ~ %s" % (rocon_uri_string, modified_rocon_uri_string) + console.reset)
assert(rocon_uri.is_compatible(rocon_uri_string, modified_rocon_uri_string) == True)
# Regex names
modified_rocon_uri_string = 'rocon:/turtlebot2/dud*/hydro/precise'
print(console.cyan + " - %s ~ %s" % (rocon_uri_string, modified_rocon_uri_string) + console.reset)
assert(rocon_uri.is_compatible(rocon_uri_string, modified_rocon_uri_string) == True)
modified_rocon_uri_string = 'rocon:/turtlebot2/dud*/hydro/precise'
print(console.cyan + " - %s ~ %s" % (modified_rocon_uri_string, rocon_uri_string) + console.reset)
assert(rocon_uri.is_compatible(modified_rocon_uri_string, rocon_uri_string) == True)
doubly_modified_rocon_uri_string = 'rocon:/turtlebot2/dudette*/hydro/precise'
print(console.cyan + " - %s ~ %s" % (modified_rocon_uri_string, doubly_modified_rocon_uri_string) + console.reset)
assert(rocon_uri.is_compatible(modified_rocon_uri_string, doubly_modified_rocon_uri_string) == True)
# No matching hardware platform
modified_rocon_uri_string = 'rocon:/pr2|waiterbot/dude'
print(console.cyan + " - %s !~ %s" % (rocon_uri_string, modified_rocon_uri_string) + console.reset)
assert(rocon_uri.is_compatible(rocon_uri_string, modified_rocon_uri_string) == False)
# Modified field
modified_rocon_uri_string = 'rocon:/turtlebot2/dudette/hydro/precise'
print(console.cyan + " - %s !~ %s" % (rocon_uri_string, modified_rocon_uri_string) + console.reset)
assert(rocon_uri.is_compatible(rocon_uri_string, modified_rocon_uri_string) == False)
invalid_rocon_uri = 'rocon:/lala|turtlebot2'
try:
rocon_uri.is_compatible(rocon_uri_string, invalid_rocon_uri)
except rocon_uri.RoconURIValueError as e:
print(console.cyan + " - %s FAILS %s [%s]" % (rocon_uri_string, invalid_rocon_uri, str(e)) + console.reset)
assert_raises(rocon_uri.RoconURIValueError, rocon_uri.is_compatible, rocon_uri_string, invalid_rocon_uri)