pyuavcan/pyuavcan_v0/__init__.py
Go to the documentation of this file.
1 #
2 # Copyright (C) 2014-2015 UAVCAN Development Team <uavcan.org>
3 #
4 # This software is distributed under the terms of the MIT License.
5 #
6 # Author: Ben Dyer <ben_dyer@mac.com>
7 # Pavel Kirienko <pavel.kirienko@zubax.com>
8 #
9 
10 """
11 Python UAVCAN package.
12 Supported Python versions: 3.2+, 2.7.
13 """
14 
15 from __future__ import division, absolute_import, print_function, unicode_literals
16 import os
17 import sys
18 import struct
19 import pkg_resources
20 import time
21 from logging import getLogger
22 
23 try:
24  # noinspection PyStatementEffect
25  time.monotonic # Works natively in Python 3.3+
26 except AttributeError:
27  try:
28  # noinspection PyPackageRequirements,PyUnresolvedReferences
29  import monotonic # 3rd party dependency for old versions @UnresolvedImport
30  # monotonic_wrapper is a temporary work around for https://github.com/UAVCAN/pyuavcan/issues/22
31  # monotonic_wrapper stops arguments being passed to monotonic.monotonic
32  def monotonic_wrapper(*args, **kwargs):
33  return monotonic.monotonic()
34  time.monotonic = monotonic_wrapper
35  except ImportError:
36  time.monotonic = time.time # Last resort - using non-monotonic time; this is no good but oh well
37  print('''The package 'monotonic' is not available, the library will use real time instead of monotonic time.
38 This implies that the library may misbehave if system clock is adjusted while the library is running.
39 In order to fix this problem, consider either option:
40  1. Switch to Python 3.
41  2. Install the missing package, e.g. using pip:
42  pip install monotonic''', file=sys.stderr)
43 
44 
45 class UAVCANException(Exception):
46  pass
47 
48 
49 from .version import __version__
50 import pyuavcan_v0.node as node
51 from pyuavcan_v0.node import make_node
52 from pyuavcan_v0.driver import make_driver
53 import pyuavcan_v0.dsdl as dsdl
54 import pyuavcan_v0.transport as transport
55 from pyuavcan_v0.transport import get_uavcan_data_type, \
56  get_active_union_field, switch_union_field, is_union, \
57  get_constants, get_fields, \
58  is_request, is_response
59 from pyuavcan_v0.introspect import value_to_constant_name, to_yaml
60 
61 
62 TRANSFER_PRIORITY_LOWEST = 31
63 TRANSFER_PRIORITY_HIGHEST = 0
64 
65 
66 logger = getLogger(__name__)
67 
68 
69 class Module(object):
70  pass
71 
72 
73 class Namespace(object):
74  """Provides a nice object-based way to look up UAVCAN data types."""
75 
76  def __init__(self):
77  self.__namespaces = set()
78 
79  # noinspection PyProtectedMember
80  def _path(self, attrpath):
81  """Returns the namespace object at the given .-separated path,
82  creating any namespaces in the path that don't already exist."""
83 
84  attr, _, subpath = attrpath.partition(".")
85  if attr not in self.__dict__:
86  self.__dict__[attr] = Namespace()
87  self.__namespaces.add(attr)
88 
89  if subpath:
90  return self.__dict__[attr]._path(subpath)
91  else:
92  return self.__dict__[attr]
93 
94  def _namespaces(self):
95  """Returns the top-level namespaces in this object"""
96  return set(self.__namespaces)
97 
98 
99 MODULE = Module()
100 DATATYPES = {}
101 TYPENAMES = {}
102 
103 
104 # noinspection PyProtectedMember
105 def load_dsdl(*paths, **args):
106  """
107  Loads the DSDL files under the given directory/directories, and creates
108  types for each of them in the current module's namespace.
109 
110  If the exclude_dist argument is not present, or False, the DSDL
111  definitions installed with this package will be loaded first.
112 
113  Also adds entries for all datatype (ID, kind)s to the DATATYPES
114  dictionary, which maps datatype (ID, kind)s to their respective type
115  classes.
116  """
117  global DATATYPES, TYPENAMES
118 
119  paths = list(paths)
120 
121  # Try to prepend the built-in DSDL files
122  # TODO: why do we need try/except here?
123  # noinspection PyBroadException
124  try:
125  if not args.get("exclude_dist", None):
126  dsdl_path = pkg_resources.resource_filename(__name__, "dsdl_files") # @UndefinedVariable
127  paths = [os.path.join(dsdl_path, "uavcan")] + paths
128  custom_path = os.path.join(os.path.expanduser("~"), "uavcan_vendor_specific_types")
129  if os.path.isdir(custom_path):
130  paths += [f for f in [os.path.join(custom_path, f) for f in os.listdir(custom_path)]
131  if os.path.isdir(f)]
132  except Exception:
133  pass
134 
135  root_namespace = Namespace()
136  dtypes = dsdl.parse_namespaces(paths)
137  for dtype in dtypes:
138  namespace, _, typename = dtype.full_name.rpartition(".")
139  root_namespace._path(namespace).__dict__[typename] = dtype
140  TYPENAMES[dtype.full_name] = dtype
141 
142  if dtype.default_dtid:
143  DATATYPES[(dtype.default_dtid, dtype.kind)] = dtype
144  # Add the base CRC to each data type capable of being transmitted
145  dtype.base_crc = dsdl.crc16_from_bytes(struct.pack("<Q", dtype.get_data_type_signature()))
146  logger.debug("DSDL Load {: >30} DTID: {: >4} base_crc:{: >8}"
147  .format(typename, dtype.default_dtid, hex(dtype.base_crc)))
148 
149  def create_instance_closure(closure_type, _mode=None):
150  # noinspection PyShadowingNames
151  def create_instance(*args, **kwargs):
152  if _mode:
153  assert '_mode' not in kwargs, 'Mode cannot be supplied to service type instantiation helper'
154  kwargs['_mode'] = _mode
155  return transport.CompoundValue(closure_type, *args, **kwargs)
156  return create_instance
157 
158  dtype._instantiate = create_instance_closure(dtype)
159 
160  if dtype.kind == dtype.KIND_SERVICE:
161  dtype.Request = create_instance_closure(dtype, _mode='request')
162  dtype.Response = create_instance_closure(dtype, _mode='response')
163 
164  namespace = root_namespace._path("uavcan")
165  for top_namespace in namespace._namespaces():
166  MODULE.__dict__[str(top_namespace)] = namespace.__dict__[top_namespace]
167 
168  MODULE.__dict__["thirdparty"] = Namespace()
169  for ext_namespace in root_namespace._namespaces():
170  if str(ext_namespace) != "uavcan":
171  # noinspection PyUnresolvedReferences
172  MODULE.thirdparty.__dict__[str(ext_namespace)] = root_namespace.__dict__[ext_namespace]
173 
174 
175 __all__ = ["dsdl", "transport", "load_dsdl", "DATATYPES", "TYPENAMES"]
176 
177 
178 # Hack to support dynamically-generated attributes at the top level of the
179 # module. It doesn't feel right but it's recommended by Guido:
180 # https://mail.python.org/pipermail/python-ideas/2012-May/014969.html
181 MODULE.__dict__ = globals()
182 MODULE._module = sys.modules[MODULE.__name__]
183 MODULE._pmodule = MODULE
184 sys.modules[MODULE.__name__] = MODULE
185 
186 
187 # Completing package initialization with loading default DSDL definitions
188 load_dsdl()
189 
190 
191 # Importing modules that may be dependent on the standard DSDL types
192 import pyuavcan_v0.app as app
pyuavcan_v0.Namespace
Definition: pyuavcan/pyuavcan_v0/__init__.py:73
pyuavcan_v0.driver
Definition: pyuavcan/pyuavcan_v0/driver/__init__.py:1
pyuavcan_v0.transport.CompoundValue
Definition: transport.py:474
pyuavcan_v0.monotonic_wrapper
def monotonic_wrapper(*args, **kwargs)
Definition: pyuavcan/pyuavcan_v0/__init__.py:32
pyuavcan_v0.load_dsdl
def load_dsdl(*paths, **args)
Definition: pyuavcan/pyuavcan_v0/__init__.py:105
pyuavcan_v0.Namespace.__init__
def __init__(self)
Definition: pyuavcan/pyuavcan_v0/__init__.py:76
libuavcan_dsdl_compiler.str
str
Definition: libuavcan_dsdl_compiler/__init__.py:22
pyuavcan_v0.UAVCANException
Definition: pyuavcan/pyuavcan_v0/__init__.py:45
pyuavcan_v0.node
Definition: node.py:1
pyuavcan_v0.Module
Definition: pyuavcan/pyuavcan_v0/__init__.py:69
pyuavcan_v0.Namespace._namespaces
def _namespaces(self)
Definition: pyuavcan/pyuavcan_v0/__init__.py:94
pyuavcan_v0.app
Definition: pyuavcan/pyuavcan_v0/app/__init__.py:1
pyuavcan_v0.dsdl
Definition: pyuavcan/pyuavcan_v0/dsdl/__init__.py:1
pyuavcan_v0.transport
Definition: transport.py:1
pyuavcan_v0.introspect
Definition: introspect.py:1
pyuavcan_v0.Namespace.__namespaces
__namespaces
Definition: pyuavcan/pyuavcan_v0/__init__.py:77
test.format
format
Definition: dsdl/test.py:6
pyuavcan_v0.Namespace._path
def _path(self, attrpath)
Definition: pyuavcan/pyuavcan_v0/__init__.py:80


uavcan_communicator
Author(s):
autogenerated on Fri Dec 13 2024 03:10:02