Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
[flake8]
max-line-length = 119
ignore =
# D10*: Missing docstring
D10
# E203: whitespace before ':'
# This error is not PEP8 complaint and should be ignored
E203
# W503: line break before binary operator
# seems to conflict with black code formatting
W503
# W605: invalid escape sequence '\d'
W605
exclude =
.git,
.tox,
.eggs,
__pycache__,
build,
dist
39 changes: 10 additions & 29 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,42 +1,23 @@
FROM debian:buster as builder
ARG BASE_IMAGE=alpine:3.17
FROM ${BASE_IMAGE}

ARG LIBDLT_VERSION=v2.18.8

RUN set -ex \
&& apt-get update \
&& apt-get upgrade -y \
&& apt-get install -y build-essential git cmake libdbus-1-dev cmake-data \
libdbus-1-dev systemd libsystemd-dev wget curl zlib1g-dev

# Install libdlt
RUN set -ex \
&& apk add --no-cache build-base musl-dev linux-headers git cmake ninja \
wget curl dbus zlib \
python3 python3-dev py3-pip py3-tox \
&& git clone https://github.com/GENIVI/dlt-daemon \
&& cd /dlt-daemon \
&& git checkout ${LIBDLT_VERSION} \
&& cd /dlt-daemon \
&& cmake CMakeLists.txt \
&& make \
&& make install

FROM debian:buster
&& make -j \
&& make install \
&& ldconfig /usr/local/lib

# Install libdlt.so
COPY --from=builder /usr/local/lib /usr/local/lib
RUN mkdir -p /workspace

RUN set -ex \
&& ldconfig

RUN set -ex \
&& apt-get update \
&& apt-get upgrade -y \
&& apt-get install -y python3 python3-pip python2 python2-dev git \
&& pip3 install --no-cache-dir setuptools tox \
&& apt-get clean all \
&& rm -rf \
/var/cache/debconf/* \
/var/lib/apt/lists/* \
/var/log/* \
/tmp/* \
/var/tmp/*
WORKDIR /workspace

# vim: set ft=dockerfile :
1 change: 1 addition & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
include LICENCE.txt
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ LIBDLT_VERSION=v2.18.8
IMAGE=python-dlt/python-dlt-unittest
TAG?=latest
DK_CMD=docker run --rm -v $(shell pwd):/pydlt -w /pydlt
TEST_ARGS?="-e py3,py27"
TEST_ARGS?="-e py3,lint"

.PHONY: all
all:
Expand Down
25 changes: 12 additions & 13 deletions README.rst → README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
python-dlt
==========
# python-dlt

python-dlt is a thin Python ctypes wrapper around libdlt functions. It was
primarily created for use with BMW's test execution framework. However,
Expand All @@ -11,16 +10,14 @@ later versions might require adaptations. The package will not support previous
versions from python-dlt v2.0. Also only GENIVI DLT daemon produced traces
have been tested.


Design
------
## Design

The code is split up into 3 primary components:

* The `core`: This subpackage provides the major chunk of ctypes wrappers for
the structures defined in libdlt. It abstracts out the libdlt structures for use
by the rest of mgu_dlt. Classes defined here ideally should *not* be used
outside of mgu_dlt. The module `core_base.py` provides the default
by the rest of python-dlt. Classes defined here ideally should *not* be used
outside of python-dlt. The module `core_base.py` provides the default
implementation of the classes and the other `core_*.py` modules provide the
overrides for the version specific implementations of libdlt. The correct version
specific implementation will be loaded automatically at runtime. (the logic for
Expand All @@ -29,11 +26,11 @@ The code is split up into 3 primary components:
* The python interface classes: These are defined in `dlt.py`. Most of the
classes here derive from their corresponding ctypes class definitions from
`core` and provide a more python friendly api/access to the underlying C/ctypes
implementations. Ideally, python code using `mgu_dlt` would use these classes
implementations. Ideally, python code using `python-dlt` would use these classes
rather than the base classes in `core`.

* API for tools: This is the component that provides common interfaces required
by the tools that use `mgu_dlt`, like the `DLTBroker`, 'DLTLifecycle' etc. These
by the tools that use `python-dlt`, like the `DLTBroker`, 'DLTLifecycle' etc. These
classes do not have equivalents in libdlt and were created based on usage
requirements (and as such make assumptions about the manner in which they would
be used).
Expand All @@ -46,7 +43,7 @@ in C and is a pretty well laid out, straight forward (ie: not many layers of
abstractions), small code base. Makes for good bedtime reading.

The rest of this document will describe and demonstrate some of the design of
the external API of mgu_dlt.
the external API of python-dlt.

The classes most relevant for users of python-dlt possibly are `DLTClient`,
`DLTFile`, `DLTMessage`, `DLTBroker`. The names hopefully make their purpose
Expand All @@ -56,6 +53,7 @@ Here are examples of some interesting ways to use these classes:

* DLTFile and DLTMessage::

```python
>>> from dlt import dlt
>>> # DLTFile object can be obtained by lading a trace file
>>> d = dlt.load("high_full_trace.dlt")
Expand All @@ -76,10 +74,12 @@ Here are examples of some interesting ways to use these classes:
... # the pickle protocol (this is to enable sharing
... # of the DLTMessage in a multiprocessing
... # environment)
```


* DLTClient and DLTBroker::

```python
>>> from dlt import dlt
>>> c = dlt.DLTClient(servIP="127.0.0.1") # Only initializes the client
>>> c.connect() # ...this connects
Expand All @@ -102,10 +102,9 @@ Here are examples of some interesting ways to use these classes:
>>> broker.start()
>>> print(ctx.wait_for(count=10))
>>>
```


Design of DLTBroker
~~~~~~~~~~~~~~~~~~~
## Design of DLTBroker

The DLTBroker abstracts out the management of 2 (multiprocessing) queues:

Expand Down
12 changes: 5 additions & 7 deletions dlt/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import collections
import logging
import subprocess

if not hasattr(subprocess, "TimeoutExpired"):
import subprocess32 as subprocess # pylint: disable=import-error

Expand All @@ -22,17 +23,14 @@ def run_command(command, timeout=60, shell=True):
:rtype: subprocess compatible ProcessResult
:raises RuntimeError: If timeout expires.
"""
process = subprocess.Popen(command,
shell=shell,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
process = subprocess.Popen(
command, shell=shell, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
try:
stdout, stderr = process.communicate(timeout=timeout)
except subprocess.TimeoutExpired:
process.terminate()
raise RuntimeError("Timeout %d seconds reached for command '%s'"
% (timeout, command))
raise RuntimeError("Timeout %d seconds reached for command '%s'" % (timeout, command))
if isinstance(stdout, bytes):
stdout = stdout.decode("utf-8")
if isinstance(stderr, bytes):
Expand Down
30 changes: 12 additions & 18 deletions dlt/core/__init__.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
# Copyright (C) 2017. BMW Car IT GmbH. All rights reserved.
"""Basic ctypes binding to the DLT library"""

# pylint: disable=invalid-name,wildcard-import

import ctypes
import os

import six

from dlt.core.core_base import *
from dlt.core.core_base import * # noqa: F403


API_VER = None
Expand All @@ -23,10 +18,7 @@ def get_version(loaded_lib):
# buf would be something like:
# DLT Package Version: X.XX.X STABLE, Package Revision: vX.XX.XX build on Jul XX XXXX XX:XX:XX
# -SYSTEMD -SYSTEMD_WATCHDOG -TEST -SHM
if six.PY3:
buf_split = buf.value.decode().split()
else:
buf_split = buf.value.split()
buf_split = buf.value.decode().split()

API_VER = buf_split[3]

Expand All @@ -35,15 +27,15 @@ def get_version(loaded_lib):

def get_api_specific_file(version):
"""Return specific version api filename, if not found fallback to first major version release"""
version_tuple = [int(num) for num in version.split('.')]
name = 'core_{}.py'.format("".join((str(num) for num in version_tuple)))
version_tuple = [int(num) for num in version.split(".")]
name = "core_{}.py".format("".join((str(num) for num in version_tuple)))
if os.path.exists(os.path.join(os.path.dirname(os.path.abspath(__file__)), name)):
return name

# The minor version does not exist, try to truncate
if version_tuple[-1] != 0:
version_tuple = version_tuple[:-1] + [0]
name = 'core_{}.py'.format("".join((str(num) for num in version_tuple)))
name = "core_{}.py".format("".join((str(num) for num in version_tuple)))
if not os.path.exists(os.path.join(os.path.dirname(os.path.abspath(__file__)), name)):
raise ImportError("No module file: {}".format(name))

Expand All @@ -55,13 +47,15 @@ def check_libdlt_version(api_ver):

python-dlt now only supports to run libdlt 2.18.5 or above.
"""
ver_info = tuple(int(num) for num in api_ver.split('.'))
ver_info = tuple(int(num) for num in api_ver.split("."))
if ver_info < (2, 18, 5):
raise ImportError("python-dlt only supports libdlt \
v2.18.5 (33fbad18c814e13bd7ba2053525d8959fee437d1) or above")
raise ImportError(
"python-dlt only supports libdlt \
v2.18.5 (33fbad18c814e13bd7ba2053525d8959fee437d1) or above"
)


API_VER = get_version(dltlib)
API_VER = get_version(dltlib) # noqa: F405
check_libdlt_version(API_VER)

# Load version specific definitions, if such a file exists, possibly
Expand All @@ -79,5 +73,5 @@ def check_libdlt_version(api_ver):
# (as opposed to loading multiple implementations in a specific order)
# to provide new/overriding implementations.
api_specific_file = get_api_specific_file(API_VER)
overrides = __import__('dlt.core.{}'.format(api_specific_file[:-3]), globals(), locals(), ['*'])
overrides = __import__("dlt.core.{}".format(api_specific_file[:-3]), globals(), locals(), ["*"])
locals().update(overrides.__dict__)
55 changes: 32 additions & 23 deletions dlt/core/core_2185.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,13 @@

class sockaddr_in(ctypes.Structure): # pylint: disable=invalid-name
"""Auxiliary definition for cDltReceiver. Defined in netinet/in.h header"""
_fields_ = [("sa_family", ctypes.c_ushort), # sin_family
("sin_port", ctypes.c_ushort),
("sin_addr", ctypes.c_byte * 4),
("__pad", ctypes.c_byte * 8)] # struct sockaddr_in is 16

_fields_ = [
("sa_family", ctypes.c_ushort), # sin_family
("sin_port", ctypes.c_ushort),
("sin_addr", ctypes.c_byte * 4),
("__pad", ctypes.c_byte * 8),
] # struct sockaddr_in is 16


class cDltReceiver(ctypes.Structure): # pylint: disable=invalid-name
Expand All @@ -42,15 +45,18 @@ class cDltReceiver(ctypes.Structure): # pylint: disable=invalid-name
struct sockaddr_in addr; /**< socket address information */
} DltReceiver;
"""
_fields_ = [("lastBytesRcvd", ctypes.c_int32),
("bytesRcvd", ctypes.c_int32),
("totalBytesRcvd", ctypes.c_int32),
("buffer", ctypes.POINTER(ctypes.c_char)),
("buf", ctypes.POINTER(ctypes.c_char)),
("backup_buf", ctypes.POINTER(ctypes.c_char)),
("fd", ctypes.c_int),
("buffersize", ctypes.c_int32),
("addr", sockaddr_in)]

_fields_ = [
("lastBytesRcvd", ctypes.c_int32),
("bytesRcvd", ctypes.c_int32),
("totalBytesRcvd", ctypes.c_int32),
("buffer", ctypes.POINTER(ctypes.c_char)),
("buf", ctypes.POINTER(ctypes.c_char)),
("backup_buf", ctypes.POINTER(ctypes.c_char)),
("fd", ctypes.c_int),
("buffersize", ctypes.c_int32),
("addr", sockaddr_in),
]


class cDltClient(ctypes.Structure): # pylint: disable=invalid-name
Expand All @@ -69,13 +75,16 @@ class cDltClient(ctypes.Structure): # pylint: disable=invalid-name
DltClientMode mode; /**< mode DltClientMode */
} DltClient;
"""
_fields_ = [("receiver", cDltReceiver),
("sock", ctypes.c_int),
("servIP", ctypes.c_char_p),
("hostip", ctypes.c_char_p),
("port", ctypes.c_int),
("serialDevice", ctypes.c_char_p),
("socketPath", ctypes.c_char_p),
("ecuid", ctypes.c_char * 4),
("baudrate", ctypes.c_uint),
("mode", ctypes.c_int)]

_fields_ = [
("receiver", cDltReceiver),
("sock", ctypes.c_int),
("servIP", ctypes.c_char_p),
("hostip", ctypes.c_char_p),
("port", ctypes.c_int),
("serialDevice", ctypes.c_char_p),
("socketPath", ctypes.c_char_p),
("ecuid", ctypes.c_char * 4),
("baudrate", ctypes.c_uint),
("mode", ctypes.c_int),
]
Loading