You're Invited:Meet the Socket Team at RSAC and BSidesSF 2026, March 23–26.RSVP
Socket
Book a DemoSign in
Socket

ltcodecs

Package Overview
Dependencies
Maintainers
2
Versions
44
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ltcodecs - pypi Package Compare versions

Comparing version
3.0.0
to
4.0.0
+219
.gitignore
_version.py
# Created by https://www.toptal.com/developers/gitignore/api/visualstudiocode,python,emacs
# Edit at https://www.toptal.com/developers/gitignore?templates=visualstudiocode,python,emacs
### Emacs ###
# -*- mode: gitignore; -*-
*~
\#*\#
/.emacs.desktop
/.emacs.desktop.lock
*.elc
auto-save-list
tramp
.\#*
# Org-mode
.org-id-locations
*_archive
# flymake-mode
*_flymake.*
# eshell files
/eshell/history
/eshell/lastdir
# elpa packages
/elpa/
# reftex files
*.rel
# AUCTeX auto folder
/auto/
# cask packages
.cask/
dist/
# Flycheck
flycheck_*.el
# server auth directory
/server/
# projectiles files
.projectile
# directory configuration
.dir-locals.el
# network security
/network-security.data
### Python ###
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
### VisualStudioCode ###
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.code-workspace
# Local History for Visual Studio Code
.history/
### VisualStudioCode Patch ###
# Ignore all local history of files
.history
.ionide
# End of https://www.toptal.com/developers/gitignore/api/visualstudiocode,python,emacs
.vscode/settings.json
src/test.txt
launch/.vscode/settings.json
src/commandSender.py
src/database/databases/hostCommands.db
src/database/databases/remoteCommands.db
src/uploadedFiles/.gitkeep
build_test_image:
image: docker:stable
stage: build
tags:
- privileged
services:
- name: docker:dind
script:
- docker build --rm -t ltcodecs-tests:latest -f tests/tests.Dockerfile .
build_auto-doc_image:
image: docker:stable
stage: build
tags:
- privileged
services:
- name: docker:dind
script:
- docker build --rm -t ltcodecs-docs:latest -f docs/auto-docs.Dockerfile .
trigger-ros_acomms-master-pipeline:
trigger:
project: acomms/ros_acomms
branch: master
strategy: depend
trigger-ros_acomms-devel-pipeline:
trigger:
project: acomms/ros_acomms
branch: devel
strategy: depend
test:
image: ltcodecs-tests:latest
stage: test
script:
- source /ros_entrypoint.sh
- pip install -r requirements.txt
- pip install .
- pytest --capture=no --junitxml=results.xml --cov=ltcodecs --cov-report=term --cov-report=xml --cov-report=html tests/
artifacts:
paths:
- 'coverage.xml'
- 'htmlcov/'
reports:
junit: 'results.xml'
coverage_report:
coverage_format: cobertura
path: coverage.xml
coverage: '/TOTAL\s+\d+\s+\d+\s+(\d+)%/'
test-gitlab:
image: ltcodecs-tests:latest
stage: test
script:
- source /ros_entrypoint.sh
- pip install -r requirements.txt
- git clone https://gitlab-ci-token:$CI_JOB_TOKEN@git.whoi.edu/ros/armw.git ~/armw
- cd ~/armw && pip install .
- cd $CI_PROJECT_DIR
- pip install .
- pytest --capture=no --junitxml=results.xml --cov=ltcodecs --cov-report=term --cov-report=xml --cov-report=html tests/
artifacts:
paths:
- 'coverage.xml'
- 'htmlcov/'
reports:
junit: 'results.xml'
coverage_report:
coverage_format: cobertura
path: coverage.xml
coverage: '/TOTAL\s+\d+\s+\d+\s+(\d+)%/'
auto-docs:
image: ltcodecs-docs:latest
stage: deploy
script:
- pip install -r requirements.txt
- pip install .
- cd docs
- make latexpdf
- mv _build/latex/ltcodecs.pdf ..
artifacts:
paths:
- ltcodecs.pdf
pages:
image: ltcodecs-docs:latest
stage: deploy
script:
- pip install -r requirements.txt
- pip install .
- cd docs
- sphinx-build -b html . ../public
artifacts:
paths:
- public
only:
- tags
- master
pypi:
image: python
stage: deploy
script:
- pip install -r requirements.txt
- pip install build twine
- python -m build
- twine upload --username __token__ --password $PYPI_TOKEN dist/*
artifacts:
paths:
- dist/
only:
- tags
If I am not a WHOI employee, I agree to the terms in the [WHOI Contributor Agreement](CONTIBUTING.md) (`CONTRIBUTING.md`) in this repository.
Contributor License Agreement
=============================
This Contributor License Agreement (the “Agreement”) is between Woods Hole Oceanographic Institution and the person or entity designated in this Agreement as the Contributor (and sometimes referred to as “You” or “Your” below). You agree to the terms and conditions of this Agreement as of the date of such acceptance.
This Agreement is meant to clarify the intellectual property license granted with Contributions by You. This Agreement is meant to protect both You as a Contributor and WHOI as the recipient of the Contribution, and does not change your rights to use your own Contributions for any other purpose.
You accept and agree to the following terms and conditions for Your present and future Contributions submitted to WHOI. Except for the license granted herein to WHOI and recipients of related Work distributed by WHOI, You reserve all right, title and interest in and to Your Contributions.
## 1. Definitions.
"You" (or "Your") shall mean the copyright owner or legal entity authorized by the copyright owner that is making this Agreement with WHOI. For legal entities, the entity making a Contribution and all other entities that control, are controlled by, or are under common control with that entity are considered to be a single Contributor. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares or other equity interests, or (iii) beneficial ownership of such entity.
"Contribution" shall mean any original work of authorship, including any modifications or additions to an existing work, that is intentionally submitted by You to WHOI for inclusion in, or documentation of, any of the developments, works or products owned or managed by WHOI (the "Work"). For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to WHOI or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, WHOI for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by You as "Not a Contribution."
## 2. Grant of Copyright License.
Subject to the terms and conditions of this Agreement, You hereby grant to WHOI and to recipients of any Work distributed by WHOI a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your Contributions and such derivative works.
## 3. Grant of Patent License.
Subject to the terms and conditions of this Agreement, You hereby grant to WHOI and to recipients of any Work distributed by WHOI a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by You that are necessarily infringed by Your Contribution(s) alone or by combination of Your Contribution(s) with the Work to which such Contribution(s) was submitted. If any entity institutes patent litigation against You or any other entity (including a cross-claim or counterclaim in a lawsuit) alleging that your Contribution, or the Work to which you have contributed, constitutes direct or contributory patent infringement, then any patent licenses granted to that entity under this Agreement for that Contribution or Work shall terminate as of the date such litigation is filed.
## 4. Representations By You.
You represent that you are legally entitled to grant the above license. If your employer(s) has rights to intellectual property that you create that includes your Contributions, you represent that you have received permission to make Contributions on behalf of that employer, that your employer has waived such rights for your Contributions to WHOI, or that your employer has executed a separate contributor license agreement with WHOI. You represent that each of Your Contributions is Your original creation (see section 6 for submissions on behalf of others). You represent that Your Contribution submissions include complete details of any third-party license or other restriction (including, but not limited to, related patents and trademarks) of which you are personally aware and which are associated with any part of Your Contributions.
## 5. Support Matters.
You are not expected to provide support for Your Contributions, except to the extent You desire to provide support. You may provide support for free, for a fee (which must be mutually agreed by WHOI), or not at all.
## 6. Disclaimer of Certain Warranties.
UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING (INCLUDING AS AGREED TO IN THIS AGREEMENT), YOU PROVIDE YOUR CONTRIBUTIONS ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON- INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
## 7. Submitting Material Other Than Your Original Creations.
Should You wish to submit any material that is not Your original creation, You may submit it to WHOI separately from any Contribution, identifying the complete details of its source and of any license or other restriction (including, but not limited to, related patents, trademarks, and license agreements) of which you are personally aware, and conspicuously marking the material as "Submitted on behalf of a third-party: [named here]".
## 8. Notification of Inaccurate Representations.
You agree to notify WHOI of any facts or circumstances of which you become aware that would make any of the representations in this Agreement inaccurate in any respect.
FROM ros:noetic-ros-core
RUN apt-get update && apt-get upgrade -y
RUN apt install python3-pip -y
RUN apt-get install --no-install-recommends -y \
graphviz \
imagemagick \
make \
\
latexmk \
lmodern \
fonts-freefont-otf \
texlive-latex-recommended \
texlive-latex-extra \
texlive-fonts-recommended \
texlive-fonts-extra \
texlive-lang-cjk \
texlive-lang-chinese \
texlive-lang-japanese \
texlive-luatex \
texlive-xetex \
xindy \
tex-gyre \
&& apt-get autoremove \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
RUN pip install -U sphinx sphinx-book-theme myst_parser pytest
import os
import sys
sys.path.insert(0, os.path.abspath(".."))
# Configuration file for the Sphinx documentation builder.
#
# For the full list of built-in configuration values, see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
# -- Project information -----------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
project = "ltcodecs"
copyright = "2023, Woods Hole Oceanographic Institution"
author = "Woods Hole Oceanographic Institution — Acomms Group"
release = os.getenv('CI_COMMIT_REF_NAME', 'latest')
# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
# Napoleon allows using numpy- or Google-style docstrings
extensions = ["myst_parser", "sphinx.ext.autodoc", "sphinx.ext.napoleon"]
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
# -- Options for LaTeX output ------------------------------------------------
# Disable index page
latex_elements = {
'makeindex': '',
'printindex': '',
}
# -- Options for HTML output -------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
html_theme = "sphinx_book_theme"
add_function_parentheses = True
add_module_names = True
.. ltcodecs documentation master file, created by
sphinx-quickstart on Tue Jun 6 11:03:07 2023.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Welcome to ltcodecs's documentation!
====================================
There are aliases for each codec that can be used in codec yaml files.
Note that there are multiple aliases for some codec classes.
======================== ====================================================
Alias Codec Class
======================== ====================================================
``integer`` :py:class:`~ltcodecs.varint_codec.VarintCodec`
``fixedint`` :py:class:`~ltcodecs.fixedint_codec.FixedIntCodec`
``varint`` :py:class:`~ltcodecs.varint_codec.VarintCodec`
``float`` :py:class:`~ltcodecs.float_codec.FloatCodec`
``linspace_float`` :py:class:`~ltcodecs.linspace_float_codec.LinspaceFloatCodec`
``linspace`` :py:class:`~ltcodecs.linspace_float_codec.LinspaceFloatCodec`
``uint8`` :py:class:`~ltcodecs.fixedint_codec.UInt8Codec`
``uint16`` :py:class:`~ltcodecs.fixedint_codec.UInt16Codec`
``uint32`` :py:class:`~ltcodecs.fixedint_codec.UInt32Codec`
``uint64`` :py:class:`~ltcodecs.fixedint_codec.UInt64Codec`
``int8`` :py:class:`~ltcodecs.fixedint_codec.Int8Codec`
``int16`` :py:class:`~ltcodecs.fixedint_codec.Int16Codec`
``int32`` :py:class:`~ltcodecs.fixedint_codec.Int32Codec`
``int64`` :py:class:`~ltcodecs.fixedint_codec.Int64Codec`
``float32`` :py:class:`~ltcodecs.ieee_float_codec.IeeeFloat32Codec`
``float64`` :py:class:`~ltcodecs.ieee_float_codec.IeeeFloat64Codec`
``bool`` :py:class:`~ltcodecs.bool_codec.BoolCodec`
``string`` :py:class:`~ltcodecs.string_codecs.AsciiStringCodec`
``ascii`` :py:class:`~ltcodecs.string_codecs.AsciiStringCodec`
``bytes`` :py:class:`~ltcodecs.bytes_codec.BytesCodec`
``msg`` :py:class:`~ltcodecs.ros_msg_field_codec.RosMsgFieldCodec`
``ros_msg`` :py:class:`~ltcodecs.ros_msg_field_codec.RosMsgFieldCodec`
``variable_len_array`` :py:class:`~ltcodecs.variable_len_array_codec.VariableLenArrayCodec`
``fixed_len_array`` :py:class:`~ltcodecs.fixed_len_array_codec.FixedLenArrayCodec`
``ccl_latlon`` :py:class:`~ltcodecs.ccl_latlon_codec.CclLatLonCodec`,
``ccl_latlon_bcd`` :py:class:`~ltcodecs.ccl_latlon_bcd_codec.CclLatLonBcdCodec`
``pad`` :py:class:`~ltcodecs.padding_codec.PaddingCodec`
``padding`` :py:class:`~ltcodecs.padding_codec.PaddingCodec`
``time`` :py:class:`~ltcodecs.rostime_codec.RosTimeCodec`
``rostime`` :py:class:`~ltcodecs.rostime_codec.RosTimeCodec`
``string_enum`` :py:class:`~ltcodecs.string_enum_codec.StringEnumCodec`
``lzma`` :py:class:`~ltcodecs.lzma_codec.LzmaCodec`
``optional`` :py:class:`~ltcodecs.optional_field_codec.OptionalFieldCodec`
======================== ====================================================
.. toctree::
:maxdepth: 4
:caption: Contents:
ltcodecs
tests
ltcodecs
================
ltcodecs.bool\_codec module
---------------------------
.. automodule:: ltcodecs.bool_codec
:members:
:undoc-members:
:show-inheritance:
ltcodecs.bytes\_codec module
----------------------------
.. automodule:: ltcodecs.bytes_codec
:members:
:undoc-members:
:show-inheritance:
ltcodecs.ccl\_latlon\_bcd\_codec module
---------------------------------------
.. automodule:: ltcodecs.ccl_latlon_bcd_codec
:members:
:undoc-members:
:show-inheritance:
ltcodecs.ccl\_latlon\_codec module
----------------------------------
.. automodule:: ltcodecs.ccl_latlon_codec
:members:
:undoc-members:
:show-inheritance:
ltcodecs.exceptions module
--------------------------
.. automodule:: ltcodecs.exceptions
:members:
:undoc-members:
:show-inheritance:
ltcodecs.field\_codec module
----------------------------
.. automodule:: ltcodecs.field_codec
:members:
:undoc-members:
:show-inheritance:
ltcodecs.fixed\_len\_array\_codec module
----------------------------------------
.. automodule:: ltcodecs.fixed_len_array_codec
:members:
:undoc-members:
:show-inheritance:
ltcodecs.fixedint\_codec module
-------------------------------
.. automodule:: ltcodecs.fixedint_codec
:members:
:undoc-members:
:show-inheritance:
ltcodecs.float\_codec module
----------------------------
.. automodule:: ltcodecs.float_codec
:members:
:undoc-members:
:show-inheritance:
ltcodecs.ieee\_float\_codec module
----------------------------------
.. automodule:: ltcodecs.ieee_float_codec
:members:
:undoc-members:
:show-inheritance:
ltcodecs.linspace\_float\_codec module
--------------------------------------
.. automodule:: ltcodecs.linspace_float_codec
:members:
:undoc-members:
:show-inheritance:
ltcodecs.lzma\_codec module
---------------------------
.. automodule:: ltcodecs.lzma_codec
:members:
:undoc-members:
:show-inheritance:
ltcodecs.optional\_field\_codec module
---------------------------
.. automodule:: ltcodecs.optional_field_codec
:members:
:undoc-members:
:show-inheritance:
ltcodecs.padding\_codec module
------------------------------
.. automodule:: ltcodecs.padding_codec
:members:
:undoc-members:
:show-inheritance:
ltcodecs.ros\_message\_codec module
-----------------------------------
.. automodule:: ltcodecs.ros_message_codec
:members:
:undoc-members:
:show-inheritance:
ltcodecs.ros\_msg\_field\_codec module
--------------------------------------
.. automodule:: ltcodecs.ros_msg_field_codec
:members:
:undoc-members:
:show-inheritance:
ltcodecs.rostime\_codec module
------------------------------
.. automodule:: ltcodecs.rostime_codec
:members:
:undoc-members:
:show-inheritance:
ltcodecs.string\_codecs module
------------------------------
.. automodule:: ltcodecs.string_codecs
:members:
:undoc-members:
:show-inheritance:
ltcodecs.string\_enum\_codec module
-----------------------------------
.. automodule:: ltcodecs.string_enum_codec
:members:
:undoc-members:
:show-inheritance:
ltcodecs.variable\_len\_array\_codec module
-------------------------------------------
.. automodule:: ltcodecs.variable_len_array_codec
:members:
:undoc-members:
:show-inheritance:
ltcodecs.varint\_codec module
-----------------------------
.. automodule:: ltcodecs.varint_codec
:members:
:undoc-members:
:show-inheritance:
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = .
BUILDDIR = _build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
ltcodec tests
=============
Submodules
----------
tests.test\_codecs module
-------------------------
.. automodule:: tests.test_codecs
:members:
:undoc-members:
:show-inheritance:
Module contents
---------------
.. automodule:: tests
:members:
:undoc-members:
:show-inheritance:
bitstring
msgpack
crccheck
rospy-yaml-include
armw
armw
bitstring
msgpack
crccheck
rospy-yaml-include
data:
codec: string
max_length: 10
FROM ros:noetic-ros-core
# install ros package
RUN apt-get update && apt-get upgrade -y
RUN apt install python3-pip git -y
RUN pip install -U pytest pytest-cov
+20
-11

@@ -1,16 +0,24 @@

Metadata-Version: 2.1
Metadata-Version: 2.4
Name: ltcodecs
Version: 3.0.0
Summary: LT Codecs
Home-page: https://git.whoi.edu/acomms/ltcodec/
Author: whoi
Author-email: egallimore@whoi.edu
Project-URL: Bug Tracker, https://git.whoi.edu/acomms/ltcodec/
Project-URL: Documentation, https://acomms.pages.whoi.edu/ltcodec/
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+)
Classifier: Operating System :: OS Independent
Version: 4.0.0
Summary: LT Codecs: Lightweight codecs for use over low-throughput links
Author: Woods Hole Oceanographic Institution, Acoustic Communications Group
License: LGPL-3.0-or-later
Project-URL: homepage, https://git.whoi.edu/acomms/ltcodec/
Project-URL: documentation, https://acomms.pages.whoi.edu/ltcodec/
Keywords: Library,Python Modules,Scientific/Engineering
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Scientific/Engineering
Requires-Python: >=3.6
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: armw
Requires-Dist: bitstring
Requires-Dist: msgpack
Requires-Dist: crccheck
Requires-Dist: rospy-yaml-include
Dynamic: license-file

@@ -28,1 +36,2 @@ # LT Codecs

Install from Pypi via `pip install ltcodecs`
[setup.cfg](setup.cfg)

@@ -0,6 +1,39 @@

[project]
name = "ltcodecs"
dynamic = ["version"]
description = "LT Codecs: Lightweight codecs for use over low-throughput links"
keywords = ["Library", "Python Modules", "Scientific/Engineering"]
classifiers = [
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"Intended Audience :: Science/Research",
"Topic :: Software Development :: Libraries :: Python Modules",
"Topic :: Scientific/Engineering",
]
requires-python = ">=3.6"
dependencies = ["armw", "bitstring", "msgpack", "crccheck", "rospy-yaml-include"]
readme = {file = "README.md", content-type = "text/markdown"}
[project.license]
text = "LGPL-3.0-or-later"
[[project.authors]]
name = "Woods Hole Oceanographic Institution, Acoustic Communications Group"
[project.urls]
homepage = "https://git.whoi.edu/acomms/ltcodec/"
documentation = "https://acomms.pages.whoi.edu/ltcodec/"
[project.scripts]
# No scripts for now; we may add scripts in /bin in a future release
[project.optional-dependencies]
# No optional dependencies
[build-system]
requires = [
"setuptools>=42",
"wheel"
]
build-backend = "setuptools.build_meta"
requires = ["setuptools>=64", "wheel", "setuptools_scm>=8"]
build-backend = "setuptools.build_meta"
[tool.setuptools_scm]
write_to = "_version.py"

@@ -12,1 +12,2 @@ # LT Codecs

Install from Pypi via `pip install ltcodecs`
[setup.cfg](setup.cfg)

@@ -1,28 +0,1 @@

[metadata]
name = ltcodecs
version = 3.0.0
author = whoi
author_email = egallimore@whoi.edu
description = LT Codecs
long_description = file: README.md
long_description_content_type = text/markdown
url = https://git.whoi.edu/acomms/ltcodec/
project_urls =
Bug Tracker = https://git.whoi.edu/acomms/ltcodec/
Documentation = https://acomms.pages.whoi.edu/ltcodec/
classifiers =
Programming Language :: Python :: 3
License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+)
Operating System :: OS Independent
[options]
package_dir =
= src
packages = find:
python_requires = >=3.6
include_package_data = True
[options.packages.find]
where = src
[egg_info]

@@ -29,0 +2,0 @@ tag_build =

@@ -1,16 +0,24 @@

Metadata-Version: 2.1
Metadata-Version: 2.4
Name: ltcodecs
Version: 3.0.0
Summary: LT Codecs
Home-page: https://git.whoi.edu/acomms/ltcodec/
Author: whoi
Author-email: egallimore@whoi.edu
Project-URL: Bug Tracker, https://git.whoi.edu/acomms/ltcodec/
Project-URL: Documentation, https://acomms.pages.whoi.edu/ltcodec/
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+)
Classifier: Operating System :: OS Independent
Version: 4.0.0
Summary: LT Codecs: Lightweight codecs for use over low-throughput links
Author: Woods Hole Oceanographic Institution, Acoustic Communications Group
License: LGPL-3.0-or-later
Project-URL: homepage, https://git.whoi.edu/acomms/ltcodec/
Project-URL: documentation, https://acomms.pages.whoi.edu/ltcodec/
Keywords: Library,Python Modules,Scientific/Engineering
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Scientific/Engineering
Requires-Python: >=3.6
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: armw
Requires-Dist: bitstring
Requires-Dist: msgpack
Requires-Dist: crccheck
Requires-Dist: rospy-yaml-include
Dynamic: license-file

@@ -28,1 +36,2 @@ # LT Codecs

Install from Pypi via `pip install ltcodecs`
[setup.cfg](setup.cfg)

@@ -0,5 +1,15 @@

.gitignore
.gitlab-ci.yml
CONTRIBUTING.md
LICENSE
README.md
pyproject.toml
setup.cfg
requirements.txt
.gitlab/merge_request_templates/Default.md
docs/Makefile
docs/auto-docs.Dockerfile
docs/conf.py
docs/index.rst
docs/ltcodecs.rst
docs/tests.rst
src/ltcodecs/__init__.py

@@ -31,3 +41,7 @@ src/ltcodecs/bool_codec.py

src/ltcodecs.egg-info/dependency_links.txt
src/ltcodecs.egg-info/requires.txt
src/ltcodecs.egg-info/top_level.txt
tests/test_codecs.py
tests/__init__.py
tests/string_msg_codec.yaml
tests/test_codecs.py
tests/tests.Dockerfile

@@ -0,0 +0,0 @@ """

@@ -0,0 +0,0 @@ """

@@ -0,0 +0,0 @@ """

@@ -0,0 +0,0 @@ """

@@ -0,0 +0,0 @@ """

@@ -0,0 +0,0 @@ """

@@ -0,0 +0,0 @@ """

@@ -0,0 +0,0 @@ """

@@ -0,0 +0,0 @@ """

@@ -20,3 +20,3 @@ """

@abstractmethod
def encode_multiple(self, value: Any, message_dict: dict) -> tuple[Bits, Any]:
def encode_multiple(self, value: Any, message_dict: dict) -> tuple[Bits, bool, dict]:
"""

@@ -23,0 +23,0 @@ encodes multiple fields

"""
ltcodecs.nullable_codec
ltcodecs.optional_field_codec
------------------------------
This module contains the OptionalCodec class, which uses a boolean field to control whether a target field is optionally
encoded.
This module contains the OptionalCodec class, which uses a boolean field to control whether a set of target fields
is encoded in the message (making those fields optional).
"""

@@ -19,12 +19,11 @@

"""
codec for optional fields, where a boolean field controls whether a "target" field should be encoded.
codec for optional fields, where a boolean field controls whether "target" fields should be encoded.
If the controlling field is true, the target field will be encoded using target_params. If false, the
target_field won't be encoded.
If the controlling boolean field is true, the target fields will be encoded using parameters in the target_fields
dictionary (much like ros messages are encoded). If false, the target fields won't be encoded (thus using no
space in the encoded message).
Args:
target_field: Target field name (used to target a single field). If this is set, target_fields must not be set.
target_fields: Dict containing fields and associated parameters. Cannot be set if target_field is set.
target_type: ROS type of the target field (as a string)
target_params: dictionary with target field codec parameters
target_fields: Dict containing fields and associated parameters.
In the form {field_name: {codec: <codec name>, <codec_param>, etc.}}
"""

@@ -31,0 +30,0 @@

@@ -0,0 +0,0 @@ """

@@ -15,10 +15,9 @@ """

from copy import copy
import operator
from std_msgs.msg import Header
import rospy
from genpy import Message
from rospy_yaml_include.yaml_include import RospyYamlInclude
import yaml
from rospy_yaml_include.yaml_include import RospyYamlInclude
import armw
class RosMessageCodec(object):

@@ -29,3 +28,3 @@ """

def __init__(self, ros_type: Union[Message, str], fields_dict: dict = None, checksum=None):
def __init__(self, ros_type: Union[None, str], fields_dict: dict = None, checksum=None):
self.ros_type = ros_type

@@ -37,10 +36,5 @@ self.packet_codec = None

self.metadata_encoder_fields = {}
for field_name, field_params in fields_dict.items():
# We only support a few metadata fields for encoding
codec_name = field_params.get("codec", "auto")
for field_name, field_params in fields_dict.items():
# We only support a few metadata fields for encoding
codec_name = field_params.get("codec", "auto")
if codec_name in (ltcodecs.metadata_encoders.keys()):

@@ -55,3 +49,3 @@ self.metadata_encoder_fields[field_name] = codec_name

def encode(self, ros_msg: rospy.AnyMsg) -> tuple[Bits, dict[Any]]:
def encode(self, ros_msg: armw.AnyMsg) -> tuple[Bits, dict[Any]]:
"""

@@ -78,4 +72,4 @@ Encode a ROS message into a bitstream and metadata dictionary

def decode(
self, bits_to_decode: ConstBitStream, received_packet=None
) -> rospy.AnyMsg:
self, bits_to_decode: ConstBitStream, received_packet=None
) -> armw.AnyMsg:
"""

@@ -87,3 +81,6 @@ Decode a ROS message from a bitstream

rospy.loginfo(f"Decoding ROS message {self.ros_type}")
if armw.NODE():
armw.NODE().log_info(f"Decoding ROS message {self.ros_type}")
else:
print(f"Decoding ROS message {self.ros_type}")
# Now, check CRC, if required.

@@ -111,3 +108,6 @@ if self.checksum:

rospy.loginfo(f"ROS Message: {ros_msg}")
if armw.NODE():
armw.NODE().log_info(f"ROS Message: {ros_msg}")
else:
print(f"ROS Message: {ros_msg}")
return ros_msg

@@ -114,0 +114,0 @@

@@ -5,3 +5,3 @@ """

This module contains the the field codec which is used to encode and decode ROS messages.
This module contains the field codec which is used to encode and decode ROS messages.
"""

@@ -14,5 +14,4 @@

from genpy import Message
from typing import Union, Any
import roslib.message
from typing import Union, Any, Dict
import armw

@@ -28,8 +27,17 @@ import ltcodecs as ltcodecs

"""
field codec for ROS messages
Field codec for ROS messages
"""
def __init__(
self, ros_type: Union[str, Message], fields: dict = None, **kwargs
) -> None:
def __init__(self, ros_type: Union[str, None], fields: dict = None, **kwargs) -> None:
"""
Instantiate a ROS message field codec.
:param ros_type: The ROS message type, either as a string or a ROS Message object
:type ros_type: Union[str, Message]
:param fields: The fields of the ROS message, defaults to None.
:type fields: dict, optional
:param kwargs: Additional keyword arguments. Unused by this field codec.
:type kwargs: dict
"""
super().__init__(**kwargs)
self.fields = fields

@@ -39,3 +47,3 @@ self.ros_type = ros_type

if isinstance(ros_type, str):
msg_class = roslib.message.get_message_class(ros_type)
msg_class = armw.import_message_from_name(ros_type)
if not msg_class:

@@ -50,8 +58,5 @@ raise TypeError(f'Invalid ROS type "{ros_type}" for message codec {id}')

if not self.fields:
slot_names = msg_class.__slots__
slot_types = msg_class._slot_types
slots = armw.get_msg_fields_and_types(msg_class)
slots = dict(zip(slot_names, slot_types))
new_fields = dict.fromkeys(slot_names)
new_fields = dict.fromkeys(slots.keys())
for field_name in new_fields:

@@ -113,7 +118,11 @@ msg_type = slots[field_name]

def encode(self, message: Message, metadata=None) -> tuple[BitArray, dict[Any]]:
def encode(self, message: None, metadata=None) -> tuple[BitArray, dict[Any]]:
"""
encode a ROS message
Encodes the given ROS message
:param message: the message to encode
:param message: The ROS message to be encoded.
:param metadata: Optional metadata (e.g. received packet information) to be used during encoding. Some field
codecs can use this information.
:return: A tuple containing the encoded bits and a dictionary with the encoded values.
:rtype: tuple[BitArray, dict[Any]]
"""

@@ -123,14 +132,20 @@ # ROS messages use __slots__, so we can't use __dict__ or vars() to get the attributes as a dict

for field in message.__slots__:
message_dict[field] = getattr(message, field)
if field[0] == "_": # ROS2 slots start with _ for some reason
dict_field = field[1:]
else:
dict_field = field
message_dict[dict_field] = getattr(message, field)
encoded_bits = BitArray()
encoded_dict = {}
for field_name, field_params in self.fields.items():
field_codec = self.field_codecs.get(field_name, None)
# Note that metadata encoding is done at the ros_msg_codec level, not here
if not field_codec or isinstance(field_codec, str):
continue
try:
field_codec = self.field_codecs[field_name]
# Note that metadata encoding is done at the ros_msg_codec level, not here
if not field_codec or isinstance(field_codec, str):
continue
if isinstance(field_codec, MultipleFieldCodec):
field_bits, encoded_dict[field_name], encoded_fields_dict = field_codec.encode_multiple(message_dict[field_name], message_dict)
field_bits, encoded_dict[field_name], encoded_fields_dict = field_codec.encode_multiple(
message_dict[field_name], message_dict)
encoded_dict = {**encoded_dict, **encoded_fields_dict}

@@ -147,9 +162,25 @@ else:

def decode(self, bits_to_decode: ConstBitStream, metadata=None) -> Message:
def decode(self, bits_to_decode: ConstBitStream, metadata=None) -> None:
"""
decode a ROS message
Decode a ROS message from a BitStream
:param bits_to_decode: the bits to decode
:param bits_to_decode: The bitstream containing the encoded message bits.
:param metadata: Optional metadata to be used for decoding certain fields.
:return: The decoded message as a Message object.
This method decodes an encoded message using the provided bitstream and optional metadata. It iterates
through the fields in the message and uses the corresponding field codec to decode each field.
If a nested field codec is a string, it is treated as a metadata codec. If metadata is not provided or the
metadata codec is unrecognized, the field is skipped.
If a field codec is an instance of the same class (a nested RosMessageCodec), it recursively calls the decode
method on that field codec, passing the bitstream and metadata.
If a field codec is a MultipleFieldCodec, it decodes multiple fields from the bitstream.
Otherwise, it just uses the field codec to decode the nested field from the bitstream and add it to the message.
Finally, it constructs and returns a Message object using the decoded fields.
"""
# go through the bits in sequence until we are decoded.

@@ -190,11 +221,13 @@ # The ConstBitStream has an internal read pointer.

def decode_as_dict(self, bits_to_decode: ConstBitStream) -> dict[Any]:
"""This function is used to generate an object that we can use for calculating CRCs in the message codec
def decode_as_dict(self, bits_to_decode: ConstBitStream) -> Dict[Any, Any]:
"""
Decode the given bits as a dictionary (rather than a ROS message).
This function is primarily used to generate an object that we can use for calculating CRCs in the message codec.
It seems like a bit of a hack, but the alternative would require adding a second return value to every field
decoder. Since this only affects ROS messages, this keeps the bloat down.
:param bits_to_decode: the bits to decode
:param bits_to_decode: The bit stream to be decoded.
:return: The decoded message as a dictionary.
"""
# It seems like a bit of a hack, but the alternative would require adding a second return value to every field
# decoder. Since this only affects ROS messages, this keeps the bloat down.
decoded_message = {}

@@ -201,0 +234,0 @@ for field_name, field_params in self.fields.items():

@@ -12,6 +12,5 @@ """

from bitstring import ConstBitStream, Bits
from rospy import Time
from .field_codec import FieldCodec
import armw

@@ -39,3 +38,3 @@ class RosTimeCodec(FieldCodec):

def encode(self, value: Time) -> tuple[Bits, Time]:
def encode(self, value: armw.Time) -> tuple[Bits, armw.Time]:
"""

@@ -46,4 +45,7 @@ encode rostime

"""
value = value.to_sec()
if hasattr(value, 'sec'):
value = value.sec + value.nanosec / 1e9
else:
value = value.to_sec()
if value < self.min_value:

@@ -61,3 +63,3 @@ value = self.min_value

) # Used only for validation
rounded_value = Time.from_sec(rounded_value)
rounded_value = armw.Time.from_sec(rounded_value)
encoded_bits = Bits(uint=encoded_value, length=self.num_bits)

@@ -67,3 +69,3 @@

def decode(self, bits_to_decode: ConstBitStream) -> Time:
def decode(self, bits_to_decode: ConstBitStream) -> armw.Time:
"""

@@ -78,4 +80,4 @@ decode rostime

)
value = Time.from_sec(self.min_value + float_offset)
return value
value = armw.Time.from_sec(self.min_value + float_offset)
return armw.get_native_time_object(value)

@@ -82,0 +84,0 @@ @property

@@ -0,0 +0,0 @@ """

@@ -0,0 +0,0 @@ """

@@ -277,3 +277,3 @@ #!/usr/bin/env python3

codec = ltcodecs.VariableLenArrayCodec(
codec = ltcodecs.FixedLenArrayCodec(
"integer", 4, element_params={"min_value": 0, "max_value": 100}

@@ -426,4 +426,15 @@ )

def test_padding(self) -> None:
value = "some nonsense"
codec = ltcodecs.PaddingCodec(num_bits=19)
encoded = codec.encode(value)
bit_stream = ConstBitStream(encoded[0])
decoded_value = codec.decode(bit_stream)
assert decoded_value is None
assert len(bit_stream) == 19
if __name__ == "__main__":
sys.exit(pytest.main(['--capture=no', '--junitxml=results.xml', '--cov=ltcodecs', '--cov-report=xml', '--cov-report=term', __file__]))
sys.exit(pytest.main(['--capture=no', '--junitxml=results.xml', '--cov=ltcodecs', '--cov-report=xml', '--cov-report=html', '--cov-report=term', __file__]))