mirror of
https://github.com/nasa/fprime-tools.git
synced 2025-12-13 03:03:37 -06:00
mstarch: fixing up Fw UTs for refactored types
This commit is contained in:
parent
3be5da734b
commit
35879444ef
7
setup.py
7
setup.py
@ -1,5 +1,4 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- encoding: utf-8 -*-
|
|
||||||
####
|
####
|
||||||
# fprime Python Package:
|
# fprime Python Package:
|
||||||
#
|
#
|
||||||
@ -17,12 +16,8 @@
|
|||||||
# pip install -e ./Fw/Python
|
# pip install -e ./Fw/Python
|
||||||
# ```
|
# ```
|
||||||
###
|
###
|
||||||
from __future__ import absolute_import
|
|
||||||
from __future__ import print_function
|
|
||||||
|
|
||||||
from setuptools import find_packages
|
|
||||||
from setuptools import setup
|
|
||||||
|
|
||||||
|
from setuptools import find_packages, setup
|
||||||
|
|
||||||
# Setup a python package using setup-tools. This is a newer (and more recommended) technology
|
# Setup a python package using setup-tools. This is a newer (and more recommended) technology
|
||||||
# then distutils.
|
# then distutils.
|
||||||
|
|||||||
@ -2,8 +2,12 @@
|
|||||||
Created on May 29, 2020
|
Created on May 29, 2020
|
||||||
@author: jishii
|
@author: jishii
|
||||||
"""
|
"""
|
||||||
from .type_exceptions import ArrayLengthException, TypeMismatchException
|
|
||||||
from .type_base import ValueType
|
from .type_base import ValueType
|
||||||
|
from .type_exceptions import (
|
||||||
|
ArrayLengthException,
|
||||||
|
NotInitializedException,
|
||||||
|
TypeMismatchException,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ArrayType(ValueType):
|
class ArrayType(ValueType):
|
||||||
@ -47,8 +51,13 @@ class ArrayType(ValueType):
|
|||||||
"""
|
"""
|
||||||
JSONable type
|
JSONable type
|
||||||
"""
|
"""
|
||||||
members = {"name": self.__typename, "type": self.__typename, "size": self.__arr_size, "format": self.__arr_format,
|
members = {
|
||||||
"values": [member.to_jsonable() for member in self.val]}
|
"name": self.__typename,
|
||||||
|
"type": self.__typename,
|
||||||
|
"size": self.__arr_size,
|
||||||
|
"format": self.__arr_format,
|
||||||
|
"values": [member.to_jsonable() for member in self.val],
|
||||||
|
}
|
||||||
return members
|
return members
|
||||||
|
|
||||||
def serialize(self):
|
def serialize(self):
|
||||||
@ -64,7 +73,7 @@ class ArrayType(ValueType):
|
|||||||
item = self.arr_type()
|
item = self.arr_type()
|
||||||
item.deserialize(data, offset + i * item.getSize())
|
item.deserialize(data, offset + i * item.getSize())
|
||||||
values.append(item)
|
values.append(item)
|
||||||
self.val = valuess
|
self.val = values
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def arr_type(self):
|
def arr_type(self):
|
||||||
@ -84,4 +93,3 @@ class ArrayType(ValueType):
|
|||||||
def getSize(self):
|
def getSize(self):
|
||||||
""" Return the size of the array """
|
""" Return the size of the array """
|
||||||
return sum([item.getSize() for item in self.val])
|
return sum([item.getSize() for item in self.val])
|
||||||
|
|
||||||
|
|||||||
@ -2,10 +2,15 @@
|
|||||||
Created on Dec 18, 2014
|
Created on Dec 18, 2014
|
||||||
@author: tcanham, reder
|
@author: tcanham, reder
|
||||||
"""
|
"""
|
||||||
from __future__ import absolute_import
|
|
||||||
import struct
|
import struct
|
||||||
from .type_exceptions import DeserializeException, NotInitializedException, TypeMismatchException
|
|
||||||
from .type_base import ValueType
|
from .type_base import ValueType
|
||||||
|
from .type_exceptions import (
|
||||||
|
DeserializeException,
|
||||||
|
NotInitializedException,
|
||||||
|
TypeMismatchException,
|
||||||
|
TypeRangeException
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class BoolType(ValueType):
|
class BoolType(ValueType):
|
||||||
@ -13,12 +18,13 @@ class BoolType(ValueType):
|
|||||||
Representation of a boolean type that will be stored for F prime. True values are stored as a U8 of 0xFF and False
|
Representation of a boolean type that will be stored for F prime. True values are stored as a U8 of 0xFF and False
|
||||||
is stored as a U8 of 0x00.
|
is stored as a U8 of 0x00.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
TRUE = 0xFF
|
TRUE = 0xFF
|
||||||
FALSE = 0x00
|
FALSE = 0x00
|
||||||
|
|
||||||
def validate(self, val):
|
def validate(self, val):
|
||||||
""" Validate the given class """
|
""" Validate the given class """
|
||||||
if not isinstance(bool, val):
|
if not isinstance(val, bool):
|
||||||
raise TypeMismatchException(bool, type(val))
|
raise TypeMismatchException(bool, type(val))
|
||||||
|
|
||||||
def serialize(self):
|
def serialize(self):
|
||||||
@ -28,11 +34,12 @@ class BoolType(ValueType):
|
|||||||
return struct.pack("B", 0xFF if self.val else 0x00)
|
return struct.pack("B", 0xFF if self.val else 0x00)
|
||||||
|
|
||||||
def deserialize(self, data, offset):
|
def deserialize(self, data, offset):
|
||||||
"""
|
""" Deserialize boolean value """
|
||||||
Utilize deserialized decorator here...
|
|
||||||
"""
|
|
||||||
try:
|
try:
|
||||||
return struct.unpack_from("B", self.TRUE if self.val else self.FALSE)
|
int_val = struct.unpack_from("B", data, offset)[0]
|
||||||
|
if int_val not in [self.TRUE, self.FALSE]:
|
||||||
|
raise TypeRangeException(int_val)
|
||||||
|
self.val = int_val == self.TRUE
|
||||||
except struct.error:
|
except struct.error:
|
||||||
raise DeserializeException("Not enough bytes to deserialize bool.")
|
raise DeserializeException("Not enough bytes to deserialize bool.")
|
||||||
|
|
||||||
|
|||||||
@ -3,8 +3,15 @@ Created on Dec 18, 2014
|
|||||||
@author: tcanham, reder
|
@author: tcanham, reder
|
||||||
"""
|
"""
|
||||||
import struct
|
import struct
|
||||||
from .type_exceptions import DeserializeException, EnumMismatchException, NotInitializedException, TypeMismatchException, TypeRangeException
|
|
||||||
from .type_base import ValueType
|
from .type_base import ValueType
|
||||||
|
from .type_exceptions import (
|
||||||
|
DeserializeException,
|
||||||
|
EnumMismatchException,
|
||||||
|
NotInitializedException,
|
||||||
|
TypeMismatchException,
|
||||||
|
TypeRangeException,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class EnumType(ValueType):
|
class EnumType(ValueType):
|
||||||
@ -15,6 +22,7 @@ class EnumType(ValueType):
|
|||||||
and current value as a string. The member values will have to be computed
|
and current value as a string. The member values will have to be computed
|
||||||
containing code based on C enum rules
|
containing code based on C enum rules
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, typename="", enum_dict=None, val=None):
|
def __init__(self, typename="", enum_dict=None, val=None):
|
||||||
"""
|
"""
|
||||||
Constructor
|
Constructor
|
||||||
@ -38,8 +46,8 @@ class EnumType(ValueType):
|
|||||||
|
|
||||||
def validate(self, val):
|
def validate(self, val):
|
||||||
""" Validate the value passed into the enumeration """
|
""" Validate the value passed into the enumeration """
|
||||||
if isinstance(self.enum_dict(), dict):
|
if not isinstance(self.enum_dict(), dict):
|
||||||
raise TypeMismatchException(dict, type(val))
|
raise TypeMismatchException(dict, type(self.enum_dict()))
|
||||||
for member in self.keys():
|
for member in self.keys():
|
||||||
if not isinstance(member, str):
|
if not isinstance(member, str):
|
||||||
raise TypeMismatchException(str, type(member))
|
raise TypeMismatchException(str, type(member))
|
||||||
@ -77,8 +85,11 @@ class EnumType(ValueType):
|
|||||||
try:
|
try:
|
||||||
int_val = struct.unpack_from(">i", data, offset)[0]
|
int_val = struct.unpack_from(">i", data, offset)[0]
|
||||||
except:
|
except:
|
||||||
raise DeserializeException("Could not deserialize enum value. Needed: {} bytes Found: {}"
|
raise DeserializeException(
|
||||||
.format(self.getSize(), len(data[offset:])))
|
"Could not deserialize enum value. Needed: {} bytes Found: {}".format(
|
||||||
|
self.getSize(), len(data[offset:])
|
||||||
|
)
|
||||||
|
)
|
||||||
for key, val in self.enum_dict().items():
|
for key, val in self.enum_dict().items():
|
||||||
if int_val == val:
|
if int_val == val:
|
||||||
self.val = key
|
self.val = key
|
||||||
@ -89,5 +100,4 @@ class EnumType(ValueType):
|
|||||||
|
|
||||||
def getSize(self):
|
def getSize(self):
|
||||||
""" Calculates the size based on the size of an integer used to store it """
|
""" Calculates the size based on the size of an integer used to store it """
|
||||||
return struct.calcsize('>i');
|
return struct.calcsize(">i")
|
||||||
|
|
||||||
|
|||||||
@ -1,248 +0,0 @@
|
|||||||
# ===============================================================================
|
|
||||||
# NAME: filepacket.py
|
|
||||||
#
|
|
||||||
# DESCRIPTION: A python version of Rob Bocchino's filepacket classes
|
|
||||||
# AUTHOR: jdperez
|
|
||||||
# EMAIL: jdperez@jpl.nasa.gov
|
|
||||||
# DATE CREATED: June 17, 2015
|
|
||||||
#
|
|
||||||
# Copyright 2015, California Institute of Technology.
|
|
||||||
# ALL RIGHTS RESERVED. U.S. Government Sponsorship acknowledged.
|
|
||||||
# ===============================================================================
|
|
||||||
#
|
|
||||||
# Python standard modules
|
|
||||||
from __future__ import print_function
|
|
||||||
from __future__ import absolute_import
|
|
||||||
|
|
||||||
from abc import ABCMeta, abstractmethod
|
|
||||||
|
|
||||||
import six
|
|
||||||
from .numerical_types import U8Type, U16Type, U32Type
|
|
||||||
|
|
||||||
from enum import Enum
|
|
||||||
|
|
||||||
|
|
||||||
# PacketType = Enum('PacketType', 'START DATA END CANCEL NONE')
|
|
||||||
class PacketType(Enum):
|
|
||||||
START = 0
|
|
||||||
DATA = 1
|
|
||||||
END = 2
|
|
||||||
CANCEL = 3
|
|
||||||
NONE = 255
|
|
||||||
|
|
||||||
|
|
||||||
@six.add_metaclass(ABCMeta)
|
|
||||||
class FilePacketAbc(object):
|
|
||||||
@abstractmethod
|
|
||||||
def serialize(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def deserialize(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def getBufSize(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class Header(FilePacketAbc):
|
|
||||||
def __init__(self, pktType, seqIdx):
|
|
||||||
self.__pktType = U8Type(pktType)
|
|
||||||
self.__seqIdx = U32Type(seqIdx)
|
|
||||||
|
|
||||||
def deserialize(self, buf):
|
|
||||||
ptr = 0
|
|
||||||
|
|
||||||
self.__pktType.deserialize(buf, ptr)
|
|
||||||
ptr += self.__pktType.getSize()
|
|
||||||
|
|
||||||
self.__seqIdx.deserialize(buf, ptr)
|
|
||||||
|
|
||||||
def serialize(self):
|
|
||||||
return self.__pktType.serialize() + self.__seqIdx.serialize()
|
|
||||||
|
|
||||||
def getBufSize(self):
|
|
||||||
return self.__pktType.getSize() + self.__seqIdx.getSize()
|
|
||||||
|
|
||||||
|
|
||||||
class StartPacket(FilePacketAbc):
|
|
||||||
def __init__(self, seqIdx=None, filesize=None, srcPath="", destPath=""):
|
|
||||||
self.__header = Header(PacketType.START.value, seqIdx)
|
|
||||||
self.__filesize = U32Type(filesize)
|
|
||||||
self.__srcPathLen = U8Type(len(srcPath))
|
|
||||||
self.__srcPath = srcPath
|
|
||||||
self.__destPathLen = U8Type(len(destPath))
|
|
||||||
self.__destPath = destPath
|
|
||||||
|
|
||||||
def setSrcPath(self, path):
|
|
||||||
self.__srcPathLen = len(path)
|
|
||||||
self.__srcPath = path
|
|
||||||
|
|
||||||
def setDestPath(self, path):
|
|
||||||
self.__destPathLen = len(path)
|
|
||||||
self.__destPath = path
|
|
||||||
|
|
||||||
def getDestPath(self):
|
|
||||||
return self.__destPath
|
|
||||||
|
|
||||||
def getSrcPath(self):
|
|
||||||
return self.__srcPath
|
|
||||||
|
|
||||||
def getSrcLen(self):
|
|
||||||
return self.__srcPathLen
|
|
||||||
|
|
||||||
def getDestLen(self):
|
|
||||||
return self.__destPathLen
|
|
||||||
|
|
||||||
def getFileSize(self):
|
|
||||||
return self.__filesize
|
|
||||||
|
|
||||||
def serialize(self):
|
|
||||||
return (
|
|
||||||
self.__header.serialize()
|
|
||||||
+ self.__filesize.serialize()
|
|
||||||
+ self.__srcPathLen.serialize()
|
|
||||||
+ self.__srcPath
|
|
||||||
+ self.__destPathLen.serialize()
|
|
||||||
+ self.__destPath
|
|
||||||
)
|
|
||||||
|
|
||||||
def deserialize(self, buf):
|
|
||||||
ptr = 0
|
|
||||||
|
|
||||||
self.__header.deserialize(buf)
|
|
||||||
ptr += self.__header.getBufSize()
|
|
||||||
|
|
||||||
self.__filesize.deserialize(buf, ptr)
|
|
||||||
ptr += self.__filesize.getSize()
|
|
||||||
|
|
||||||
self.__srcPathLen.deserialize(buf, ptr)
|
|
||||||
ptr += self.__srcPathLen.getSize()
|
|
||||||
|
|
||||||
self.__srcPath = buf[ptr : self.__srcPathLen.val]
|
|
||||||
ptr += self.__srcPathLen.val
|
|
||||||
|
|
||||||
self.__destPathLen.deserialize(buf, ptr)
|
|
||||||
ptr += self.__destPathLen.getSize()
|
|
||||||
|
|
||||||
self.__destPath = buf[ptr:]
|
|
||||||
|
|
||||||
def getBufSize(self):
|
|
||||||
return (
|
|
||||||
self.__header.getBufSize()
|
|
||||||
+ self.__filesize.getSize()
|
|
||||||
+ self.__srcPathLen.getSize()
|
|
||||||
+ self.__srcPathLen.val
|
|
||||||
+ self.__destPathLen.getSize()
|
|
||||||
+ self.__destPathLen.val
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class DataPacket:
|
|
||||||
def __init__(self, seqIdx=None, byteOffset=None, dataSize=None, data=None):
|
|
||||||
self.__header = Header(PacketType.DATA.value, seqIdx)
|
|
||||||
self.__byteOffset = U32Type(byteOffset)
|
|
||||||
self.__dataSize = U16Type(dataSize)
|
|
||||||
self.__data = data
|
|
||||||
|
|
||||||
def serialize(self):
|
|
||||||
return (
|
|
||||||
self.__header.serialize()
|
|
||||||
+ self.__byteOffset.serialize()
|
|
||||||
+ self.__dataSize.serialize()
|
|
||||||
+ self.__data
|
|
||||||
)
|
|
||||||
|
|
||||||
def deserialize(self, buf):
|
|
||||||
ptr = 0
|
|
||||||
|
|
||||||
self.__header.deserialize(buf)
|
|
||||||
ptr += self.__header.getBufSize()
|
|
||||||
|
|
||||||
self.__byteOffset.deserialize(buf, ptr)
|
|
||||||
ptr += self.__byteOffset.getSize()
|
|
||||||
|
|
||||||
self.__dataSize.deserialize(buf, ptr)
|
|
||||||
ptr += self.__dataSize.getSize()
|
|
||||||
|
|
||||||
self.__data = buf[ptr:]
|
|
||||||
|
|
||||||
def getBufSize(self):
|
|
||||||
return (
|
|
||||||
self.__header.getBufSize()
|
|
||||||
+ self.__byteOffset.getSize()
|
|
||||||
+ self.__dataSize.getSize()
|
|
||||||
+ self.__dataSize.val
|
|
||||||
)
|
|
||||||
|
|
||||||
def getHeader(self):
|
|
||||||
return self.__header
|
|
||||||
|
|
||||||
def getByteOffset(self):
|
|
||||||
return self.__byteOffset
|
|
||||||
|
|
||||||
def getDataSize(self):
|
|
||||||
return self.__dataSize
|
|
||||||
|
|
||||||
def getData(self):
|
|
||||||
return self.__data
|
|
||||||
|
|
||||||
|
|
||||||
class EndPacket:
|
|
||||||
def __init__(self, seqIdx=None, xSum=None):
|
|
||||||
self.__header = Header(PacketType.END.value, seqIdx)
|
|
||||||
self.__xSum = U32Type(xSum)
|
|
||||||
|
|
||||||
def setChecksum(self, xSum):
|
|
||||||
self.__xSum = xSum
|
|
||||||
|
|
||||||
def getChecksum(self):
|
|
||||||
return self.__xSum
|
|
||||||
|
|
||||||
def serialize(self):
|
|
||||||
return self.__header.serialize() + self.__xSum.serialize()
|
|
||||||
|
|
||||||
def deserialize(self, buf):
|
|
||||||
ptr = 0
|
|
||||||
|
|
||||||
self.__header.deserialize(buf)
|
|
||||||
ptr += self.__header.getBufSize()
|
|
||||||
|
|
||||||
self.__xSum.deserialize(buf, ptr)
|
|
||||||
|
|
||||||
def getBufSize(self):
|
|
||||||
return self.__header.getBufSize() + self.__xSum.getSize()
|
|
||||||
|
|
||||||
|
|
||||||
class CancelPacket:
|
|
||||||
def __init__(self, seqIdx=None):
|
|
||||||
self.__header = Header(PacketType.CANCEL.value, seqIdx)
|
|
||||||
|
|
||||||
|
|
||||||
class FilePacket:
|
|
||||||
def __init__(self, filePacket):
|
|
||||||
self.__filePacket = filePacket
|
|
||||||
|
|
||||||
def serialize(self):
|
|
||||||
# return self.__filePacket.header.pktType.serialize() +\
|
|
||||||
# self.__filePacket.header.seqIdx.serialize() +\
|
|
||||||
# self.__filePacket.serialize()
|
|
||||||
return self.__filePacket.serialize()
|
|
||||||
|
|
||||||
def deserialize(self, buf):
|
|
||||||
ptr = 0
|
|
||||||
|
|
||||||
"""
|
|
||||||
self.__filePacket.header.pktType.deserialize(buf, ptr)
|
|
||||||
ptr += self.__filePacket.header.pktType.getSize()
|
|
||||||
|
|
||||||
self.__filePacket.header.seqIdx.deserialize(buf, ptr)
|
|
||||||
ptr += self.__seqIdx.getSize()
|
|
||||||
|
|
||||||
self.__filePacket.deserialize(buf, ptr)
|
|
||||||
"""
|
|
||||||
self.__filePacket.deserialize(buf, ptr)
|
|
||||||
|
|
||||||
def getBufSize(self):
|
|
||||||
return self.__filePacket.getBufSize()
|
|
||||||
@ -6,28 +6,57 @@ that map to stdint.h integer sizes, that is, 8-bit, 16-bit, 32-bit, and 64-bit s
|
|||||||
|
|
||||||
@author mstarch
|
@author mstarch
|
||||||
"""
|
"""
|
||||||
import re
|
|
||||||
import abc
|
import abc
|
||||||
|
import re
|
||||||
|
import struct
|
||||||
|
|
||||||
from .type_base import ValueType
|
from .type_base import ValueType
|
||||||
from .type_exceptions import DeserializeException, NotInitializedException, TypeMismatchException, TypeRangeException
|
from .type_exceptions import (
|
||||||
|
DeserializeException,
|
||||||
|
NotInitializedException,
|
||||||
|
TypeMismatchException,
|
||||||
|
TypeRangeException,
|
||||||
|
)
|
||||||
|
|
||||||
BITS_RE = re.compile(r"[IUF](\d\d?)")
|
BITS_RE = re.compile(r"[IUF](\d\d?)")
|
||||||
|
|
||||||
|
|
||||||
class NumericalType(ValueType, abc.ABC):
|
class NumericalType(ValueType, abc.ABC):
|
||||||
""" Numerical types that can be serialized using struct and are of some power of 2 byte width """
|
""" Numerical types that can be serialized using struct and are of some power of 2 byte width """
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def __get_bits(cls):
|
def get_bits(cls):
|
||||||
""" Gets the integer bits of a given type """
|
""" Gets the integer bits of a given type """
|
||||||
match = BITS_RE.match(cls)
|
match = BITS_RE.match(cls.__name__)
|
||||||
assert match, "Type {} does not follow format I#Type nor U#Type required of integer types".format(cls)
|
assert (
|
||||||
|
match
|
||||||
|
), "Type {} does not follow format I#Type U#Type nor F#Type required of numerical types".format(
|
||||||
|
cls
|
||||||
|
)
|
||||||
return int(match.group(1))
|
return int(match.group(1))
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def getSize(cls):
|
def getSize(cls):
|
||||||
""" Gets the size of the integer based on the size specified in the class name """
|
""" Gets the size of the integer based on the size specified in the class name """
|
||||||
return int(cls.__get_bits()/8)
|
return int(cls.get_bits() / 8)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
@abc.abstractmethod
|
||||||
|
def get_serialize_format():
|
||||||
|
""" Gets the format serialization string such that the class can be serialized via struct """
|
||||||
|
|
||||||
|
def serialize(self):
|
||||||
|
""" Serializes this type using struct and the val property """
|
||||||
|
if self.val is None:
|
||||||
|
raise NotInitializedException(type(self))
|
||||||
|
return struct.pack(self.get_serialize_format(), self.val)
|
||||||
|
|
||||||
|
def deserialize(self, data, offset):
|
||||||
|
""" Serializes this type using struct and the val property """
|
||||||
|
try:
|
||||||
|
self.val = struct.unpack_from(self.get_serialize_format(), data, offset)[0]
|
||||||
|
except struct.error as err:
|
||||||
|
raise DeserializeException(str(err))
|
||||||
|
|
||||||
|
|
||||||
class IntegerType(NumericalType, abc.ABC):
|
class IntegerType(NumericalType, abc.ABC):
|
||||||
@ -38,8 +67,8 @@ class IntegerType(NumericalType, abc.ABC):
|
|||||||
if not isinstance(val, int):
|
if not isinstance(val, int):
|
||||||
raise TypeMismatchException(int, type(val))
|
raise TypeMismatchException(int, type(val))
|
||||||
min_val = 0
|
min_val = 0
|
||||||
max_val = 1 << self.__get_integer_bits()
|
max_val = 1 << self.get_bits()
|
||||||
if self.startswith("I"):
|
if self.__class__.__name__.startswith("I"):
|
||||||
min_val -= int(max_val / 2)
|
min_val -= int(max_val / 2)
|
||||||
max_val -= int(max_val / 2)
|
max_val -= int(max_val / 2)
|
||||||
if val < min_val or val >= max_val:
|
if val < min_val or val >= max_val:
|
||||||
@ -66,48 +95,61 @@ class I8Type(IntegerType):
|
|||||||
|
|
||||||
class I16Type(IntegerType):
|
class I16Type(IntegerType):
|
||||||
""" Double byte integer type. Represents C shorts """
|
""" Double byte integer type. Represents C shorts """
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_serialize_format():
|
def get_serialize_format():
|
||||||
""" Allows serialization using struct """
|
""" Allows serialization using struct """
|
||||||
return ">h"
|
return ">h"
|
||||||
|
|
||||||
|
|
||||||
class I32Type(IntegerType):
|
class I32Type(IntegerType):
|
||||||
""" Four byte integer type. Represents C int32_t, """
|
""" Four byte integer type. Represents C int32_t, """
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_serialize_format():
|
def get_serialize_format():
|
||||||
""" Allows serialization using struct """
|
""" Allows serialization using struct """
|
||||||
return ">i"
|
return ">i"
|
||||||
|
|
||||||
|
|
||||||
class I64Type(IntegerType):
|
class I64Type(IntegerType):
|
||||||
""" Eight byte integer type. Represents C int64_t, """
|
""" Eight byte integer type. Represents C int64_t, """
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_serialize_format():
|
def get_serialize_format():
|
||||||
""" Allows serialization using struct """
|
""" Allows serialization using struct """
|
||||||
return ">q"
|
return ">q"
|
||||||
|
|
||||||
|
|
||||||
class U8Type(IntegerType):
|
class U8Type(IntegerType):
|
||||||
""" Single byte integer type. Represents C chars """
|
""" Single byte integer type. Represents C chars """
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_serialize_format():
|
def get_serialize_format():
|
||||||
""" Allows serialization using struct """
|
""" Allows serialization using struct """
|
||||||
return "B"
|
return "B"
|
||||||
|
|
||||||
|
|
||||||
class U16Type(IntegerType):
|
class U16Type(IntegerType):
|
||||||
""" Double byte integer type. Represents C shorts """
|
""" Double byte integer type. Represents C shorts """
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_serialize_format():
|
def get_serialize_format():
|
||||||
""" Allows serialization using struct """
|
""" Allows serialization using struct """
|
||||||
return ">H"
|
return ">H"
|
||||||
|
|
||||||
|
|
||||||
class U32Type(IntegerType):
|
class U32Type(IntegerType):
|
||||||
""" Four byte integer type. Represents C unt32_t, """
|
""" Four byte integer type. Represents C unt32_t, """
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_serialize_format():
|
def get_serialize_format():
|
||||||
""" Allows serialization using struct """
|
""" Allows serialization using struct """
|
||||||
return ">I"
|
return ">I"
|
||||||
|
|
||||||
|
|
||||||
class U64Type(IntegerType):
|
class U64Type(IntegerType):
|
||||||
""" Eight byte integer type. Represents C unt64_t, """
|
""" Eight byte integer type. Represents C unt64_t, """
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_serialize_format():
|
def get_serialize_format():
|
||||||
""" Allows serialization using struct """
|
""" Allows serialization using struct """
|
||||||
@ -116,14 +158,16 @@ class U64Type(IntegerType):
|
|||||||
|
|
||||||
class F32Type(FloatType):
|
class F32Type(FloatType):
|
||||||
""" Eight byte integer type. Represents C unt64_t, """
|
""" Eight byte integer type. Represents C unt64_t, """
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_serialize_format():
|
def get_serialize_format():
|
||||||
""" Allows serialization using struct """
|
""" Allows serialization using struct """
|
||||||
return ">f"
|
return ">f"
|
||||||
|
|
||||||
|
|
||||||
class F64Type(IntegerType):
|
class F64Type(FloatType):
|
||||||
""" Eight byte integer type. Represents C unt64_t, """
|
""" Eight byte integer type. Represents C unt64_t, """
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_serialize_format():
|
def get_serialize_format():
|
||||||
""" Allows serialization using struct """
|
""" Allows serialization using struct """
|
||||||
|
|||||||
@ -4,12 +4,9 @@ Created on Dec 18, 2014
|
|||||||
@author: tcanham
|
@author: tcanham
|
||||||
|
|
||||||
"""
|
"""
|
||||||
import copy
|
|
||||||
from __future__ import print_function
|
|
||||||
from __future__ import absolute_import
|
|
||||||
from .type_exceptions import TypeMismatchException
|
|
||||||
from .type_exceptions import NotInitializedException
|
|
||||||
from .type_base import BaseType, ValueType
|
from .type_base import BaseType, ValueType
|
||||||
|
from .type_exceptions import NotInitializedException, TypeMismatchException
|
||||||
|
|
||||||
|
|
||||||
class SerializableType(ValueType):
|
class SerializableType(ValueType):
|
||||||
@ -36,9 +33,13 @@ class SerializableType(ValueType):
|
|||||||
self.__typename = typename
|
self.__typename = typename
|
||||||
# If the member list is defined, stamp in None for any missing descriptions
|
# If the member list is defined, stamp in None for any missing descriptions
|
||||||
if mem_list:
|
if mem_list:
|
||||||
new_mem_list = [entry if len(entry) == 4 else (entry[0], entry[1], entry[2], None) for entry in mem_list]
|
new_mem_list = [
|
||||||
|
entry if len(entry) == 4 else (entry[0], entry[1], entry[2], None)
|
||||||
|
for entry in mem_list
|
||||||
|
]
|
||||||
# Set the member list then set the value
|
# Set the member list then set the value
|
||||||
self.mem_list = new_mem_list
|
self.mem_list = new_mem_list
|
||||||
|
if val is not None:
|
||||||
self.val = val
|
self.val = val
|
||||||
|
|
||||||
def validate(self, val=None):
|
def validate(self, val=None):
|
||||||
@ -52,11 +53,11 @@ class SerializableType(ValueType):
|
|||||||
# Check each of these members for correct types
|
# Check each of these members for correct types
|
||||||
if not isinstance(member_name, str):
|
if not isinstance(member_name, str):
|
||||||
raise TypeMismatchException(str, type(member_name))
|
raise TypeMismatchException(str, type(member_name))
|
||||||
elif isinstance(member_val, BaseType):
|
elif not isinstance(member_val, BaseType):
|
||||||
raise TypeMismatchException(BaseType, type(member_val))
|
raise TypeMismatchException(BaseType, type(member_val))
|
||||||
elif not isinstance(format_string, str):
|
elif not isinstance(format_string, str):
|
||||||
raise TypeMismatchException(str, type(format_string))
|
raise TypeMismatchException(str, type(format_string))
|
||||||
elif not isinstance(description, str):
|
elif description is not None and not isinstance(description, str):
|
||||||
raise TypeMismatchException(str, type(description))
|
raise TypeMismatchException(str, type(description))
|
||||||
# When a value is set and is not empty we need to set the member properties
|
# When a value is set and is not empty we need to set the member properties
|
||||||
if not val:
|
if not val:
|
||||||
@ -64,7 +65,9 @@ class SerializableType(ValueType):
|
|||||||
# If a value is supplied then check each value against the member list
|
# If a value is supplied then check each value against the member list
|
||||||
for val_member, list_entry in zip(val, self.mem_list):
|
for val_member, list_entry in zip(val, self.mem_list):
|
||||||
_, member_list_val, _, _ = list_entry
|
_, member_list_val, _, _ = list_entry
|
||||||
member_list_val.validate(val_member) # Insure that the the val_member is consistent with the existing member
|
member_list_val.validate(
|
||||||
|
val_member
|
||||||
|
) # Insure that the the val_member is consistent with the existing member
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def mem_list(self):
|
def mem_list(self):
|
||||||
@ -84,7 +87,9 @@ class SerializableType(ValueType):
|
|||||||
""" Serializes the members of the serializable """
|
""" Serializes the members of the serializable """
|
||||||
if self.mem_list is None:
|
if self.mem_list is None:
|
||||||
raise NotInitializedException(type(self))
|
raise NotInitializedException(type(self))
|
||||||
return b"".join([member_val.serialize() for _, member_val, _, _ in self.mem_list])
|
return b"".join(
|
||||||
|
[member_val.serialize() for _, member_val, _, _ in self.mem_list]
|
||||||
|
)
|
||||||
|
|
||||||
def deserialize(self, data, offset):
|
def deserialize(self, data, offset):
|
||||||
""" Deserialize the values of each of the members """
|
""" Deserialize the values of each of the members """
|
||||||
@ -98,16 +103,16 @@ class SerializableType(ValueType):
|
|||||||
@property
|
@property
|
||||||
def val(self):
|
def val(self):
|
||||||
""" Getter for .val """
|
""" Getter for .val """
|
||||||
return super().val
|
return ValueType.val.fget(self)
|
||||||
|
|
||||||
@val.setter
|
@val.setter
|
||||||
def val(self, val):
|
def val(self, val):
|
||||||
""" Setter for .val calls validate internally """
|
""" Setter for .val calls validate internally """
|
||||||
super().val = val
|
ValueType.val.fset(self, val)
|
||||||
# When a value is set, we need to set the member properties
|
# When a value is set, we need to set the member properties
|
||||||
for val_member, list_entry in zip(val, self.mem_list):
|
for val_member, list_entry in zip(val, self.mem_list):
|
||||||
_, member_list_val, _, _ = list_entry
|
_, member_list_val, _, _ = list_entry
|
||||||
list_entry.val = val_member
|
member_list_val.val = val_member
|
||||||
|
|
||||||
def getSize(self):
|
def getSize(self):
|
||||||
""" The size of a struct is the size of all the members """
|
""" The size of a struct is the size of all the members """
|
||||||
|
|||||||
@ -8,11 +8,13 @@ import struct
|
|||||||
|
|
||||||
from fprime.constants import DATA_ENCODING
|
from fprime.constants import DATA_ENCODING
|
||||||
|
|
||||||
from .type_exceptions import TypeMismatchException
|
|
||||||
from .type_exceptions import NotInitializedException
|
|
||||||
from .type_exceptions import StringSizeException
|
|
||||||
from .type_exceptions import DeserializeException
|
|
||||||
from . import type_base
|
from . import type_base
|
||||||
|
from .type_exceptions import (
|
||||||
|
DeserializeException,
|
||||||
|
NotInitializedException,
|
||||||
|
StringSizeException,
|
||||||
|
TypeMismatchException,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class StringType(type_base.ValueType):
|
class StringType(type_base.ValueType):
|
||||||
@ -20,6 +22,7 @@ class StringType(type_base.ValueType):
|
|||||||
String type representation for F prime. This is a value type that stores a half-word first for representing the
|
String type representation for F prime. This is a value type that stores a half-word first for representing the
|
||||||
length of this given string.
|
length of this given string.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, val=None, max_string_len=None):
|
def __init__(self, val=None, max_string_len=None):
|
||||||
"""
|
"""
|
||||||
Constructor to build a string
|
Constructor to build a string
|
||||||
@ -44,7 +47,9 @@ class StringType(type_base.ValueType):
|
|||||||
if self.val is None:
|
if self.val is None:
|
||||||
raise NotInitializedException(type(self))
|
raise NotInitializedException(type(self))
|
||||||
# Check string size before serializing
|
# Check string size before serializing
|
||||||
elif self.__max_string_len is not None and len(self.val) > self.__max_string_len:
|
elif (
|
||||||
|
self.__max_string_len is not None and len(self.val) > self.__max_string_len
|
||||||
|
):
|
||||||
raise StringSizeException(len(self.val), self.__max_string_len)
|
raise StringSizeException(len(self.val), self.__max_string_len)
|
||||||
# Pack the string size first then return the encoded data
|
# Pack the string size first then return the encoded data
|
||||||
buff = struct.pack(">H", len(self.val)) + self.val.encode(DATA_ENCODING)
|
buff = struct.pack(">H", len(self.val)) + self.val.encode(DATA_ENCODING)
|
||||||
@ -58,8 +63,11 @@ class StringType(type_base.ValueType):
|
|||||||
val_size = struct.unpack_from(">H", data, offset)[0]
|
val_size = struct.unpack_from(">H", data, offset)[0]
|
||||||
# Deal with not enough data left in the buffer
|
# Deal with not enough data left in the buffer
|
||||||
if len(data[offset + 2 :]) < val_size:
|
if len(data[offset + 2 :]) < val_size:
|
||||||
raise DeserializeException("Not enough data to deserialize string data. Needed: {} Left: {}"
|
raise DeserializeException(
|
||||||
.format(val_size, len(data[offset + 2:])))
|
"Not enough data to deserialize string data. Needed: {} Left: {}".format(
|
||||||
|
val_size, len(data[offset + 2 :])
|
||||||
|
)
|
||||||
|
)
|
||||||
# Deal with a string that is larger than max string
|
# Deal with a string that is larger than max string
|
||||||
elif self.__max_string_len is not None and val_size > self.__max_string_len:
|
elif self.__max_string_len is not None and val_size > self.__max_string_len:
|
||||||
raise StringSizeException(val_size, self.__max_string_len)
|
raise StringSizeException(val_size, self.__max_string_len)
|
||||||
|
|||||||
@ -16,19 +16,18 @@ time tags sent with serialized data in the fprime architecture.
|
|||||||
|
|
||||||
@bug No known bugs
|
@bug No known bugs
|
||||||
"""
|
"""
|
||||||
from __future__ import print_function
|
|
||||||
from __future__ import absolute_import
|
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
from enum import Enum
|
|
||||||
import math
|
import math
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
# Custom Python Modules
|
# Custom Python Modules
|
||||||
import fprime.common.models.serialize.numerical_types
|
import fprime.common.models.serialize.numerical_types
|
||||||
from fprime.common.models.serialize.type_exceptions import TypeException
|
|
||||||
from fprime.common.models.serialize.type_exceptions import TypeRangeException
|
|
||||||
from fprime.common.models.serialize import type_base
|
from fprime.common.models.serialize import type_base
|
||||||
|
from fprime.common.models.serialize.type_exceptions import (
|
||||||
|
TypeException,
|
||||||
|
TypeRangeException,
|
||||||
|
)
|
||||||
|
|
||||||
TimeBase = Enum(
|
TimeBase = Enum(
|
||||||
"TimeBase",
|
"TimeBase",
|
||||||
@ -55,6 +54,10 @@ class TimeType(type_base.BaseType):
|
|||||||
|
|
||||||
Used to parse, store, and create human readable versions of the time tags
|
Used to parse, store, and create human readable versions of the time tags
|
||||||
included in serialized output from fprime_gds systems
|
included in serialized output from fprime_gds systems
|
||||||
|
|
||||||
|
Note: comparisons support comparing to numbers or other instances of TimeType. If comparing to
|
||||||
|
another TimeType, these comparisons use the provided compare method. See TimeType.compare for
|
||||||
|
a description of this behavior. See comparison functions at the end.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, time_base=0, time_context=0, seconds=0, useconds=0):
|
def __init__(self, time_base=0, time_context=0, seconds=0, useconds=0):
|
||||||
@ -82,8 +85,12 @@ class TimeType(type_base.BaseType):
|
|||||||
self._check_time_base(time_base)
|
self._check_time_base(time_base)
|
||||||
self._check_useconds(useconds)
|
self._check_useconds(useconds)
|
||||||
|
|
||||||
self.__timeBase = fprime.common.models.serialize.numerical_types.U16Type(time_base)
|
self.__timeBase = fprime.common.models.serialize.numerical_types.U16Type(
|
||||||
self.__timeContext = fprime.common.models.serialize.numerical_types.U8Type(time_context)
|
time_base
|
||||||
|
)
|
||||||
|
self.__timeContext = fprime.common.models.serialize.numerical_types.U8Type(
|
||||||
|
time_context
|
||||||
|
)
|
||||||
self.__secs = fprime.common.models.serialize.numerical_types.U32Type(seconds)
|
self.__secs = fprime.common.models.serialize.numerical_types.U32Type(seconds)
|
||||||
self.__usecs = fprime.common.models.serialize.numerical_types.U32Type(useconds)
|
self.__usecs = fprime.common.models.serialize.numerical_types.U32Type(useconds)
|
||||||
|
|
||||||
@ -279,7 +286,6 @@ class TimeType(type_base.BaseType):
|
|||||||
dt = self.get_datetime(time_zone)
|
dt = self.get_datetime(time_zone)
|
||||||
|
|
||||||
# If we could convert to a valid datetime, use that, otherwise, format
|
# If we could convert to a valid datetime, use that, otherwise, format
|
||||||
# TODO use time_zone arg
|
|
||||||
if dt:
|
if dt:
|
||||||
return dt.strftime("%Y-%m-%d %H:%M:%S%z")
|
return dt.strftime("%Y-%m-%d %H:%M:%S%z")
|
||||||
else:
|
else:
|
||||||
@ -329,22 +335,16 @@ class TimeType(type_base.BaseType):
|
|||||||
self._check_time_base(time_base)
|
self._check_time_base(time_base)
|
||||||
self._check_useconds(useconds)
|
self._check_useconds(useconds)
|
||||||
|
|
||||||
self.__timeBase = fprime.common.models.serialize.numerical_types.U16Type(time_base)
|
self.__timeBase = fprime.common.models.serialize.numerical_types.U16Type(
|
||||||
|
time_base
|
||||||
|
)
|
||||||
self.__secs = fprime.common.models.serialize.numerical_types.U32Type(seconds)
|
self.__secs = fprime.common.models.serialize.numerical_types.U32Type(seconds)
|
||||||
self.__usecs = fprime.common.models.serialize.numerical_types.U32Type(useconds)
|
self.__usecs = fprime.common.models.serialize.numerical_types.U32Type(useconds)
|
||||||
|
|
||||||
def __repr__(self):
|
#The following Python special methods add support for rich comparison of TimeTypes to other
|
||||||
return "Time"
|
#TimeTypes and numbers.
|
||||||
|
|
||||||
"""
|
def get_float(self):
|
||||||
The following Python special methods add support for rich comparison of TimeTypes to other
|
|
||||||
TimeTypes and numbers.
|
|
||||||
Note: comparisons support comparing to numbers or other instances of TimeType. If comparing to
|
|
||||||
another TimeType, these comparisons use the provided compare method. See TimeType.compare for
|
|
||||||
a description of this behavior.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __get_float(self):
|
|
||||||
"""
|
"""
|
||||||
a helper method that gets the current TimeType as a float where the non-fraction is seconds
|
a helper method that gets the current TimeType as a float where the non-fraction is seconds
|
||||||
and the fraction is microseconds. This enables comparisons with numbers.
|
and the fraction is microseconds. This enables comparisons with numbers.
|
||||||
@ -352,46 +352,50 @@ class TimeType(type_base.BaseType):
|
|||||||
return self.seconds + (self.useconds / 1000000)
|
return self.seconds + (self.useconds / 1000000)
|
||||||
|
|
||||||
def __lt__(self, other):
|
def __lt__(self, other):
|
||||||
|
""" Less than """
|
||||||
if isinstance(other, TimeType):
|
if isinstance(other, TimeType):
|
||||||
return self.compare(self, other) < 0
|
return self.compare(self, other) < 0
|
||||||
else:
|
else:
|
||||||
return self.__get_float() < other
|
return self.get_float() < other
|
||||||
|
|
||||||
def __le__(self, other):
|
def __le__(self, other):
|
||||||
|
""" Less than or equal """
|
||||||
if isinstance(other, TimeType):
|
if isinstance(other, TimeType):
|
||||||
return self.compare(self, other) <= 0
|
return self.compare(self, other) <= 0
|
||||||
else:
|
else:
|
||||||
return self.__get_float() <= other
|
return self.get_float() <= other
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
|
""" Equal """
|
||||||
if isinstance(other, TimeType):
|
if isinstance(other, TimeType):
|
||||||
return self.compare(self, other) == 0
|
return self.compare(self, other) == 0
|
||||||
else:
|
else:
|
||||||
return self.__get_float() == other
|
return self.get_float() == other
|
||||||
|
|
||||||
def __ne__(self, other):
|
def __ne__(self, other):
|
||||||
|
""" Not equal """
|
||||||
if isinstance(other, TimeType):
|
if isinstance(other, TimeType):
|
||||||
return self.compare(self, other) != 0
|
return self.compare(self, other) != 0
|
||||||
else:
|
else:
|
||||||
return self.__get_float() != other
|
return self.get_float() != other
|
||||||
|
|
||||||
def __gt__(self, other):
|
def __gt__(self, other):
|
||||||
|
""" Greater than """
|
||||||
if isinstance(other, TimeType):
|
if isinstance(other, TimeType):
|
||||||
return self.compare(self, other) > 0
|
return self.compare(self, other) > 0
|
||||||
else:
|
else:
|
||||||
return self.__get_float() > other
|
return self.get_float() > other
|
||||||
|
|
||||||
def __ge__(self, other):
|
def __ge__(self, other):
|
||||||
|
""" Greater than or equal """
|
||||||
if isinstance(other, TimeType):
|
if isinstance(other, TimeType):
|
||||||
return self.compare(self, other) >= 0
|
return self.compare(self, other) >= 0
|
||||||
else:
|
else:
|
||||||
return self.__get_float() >= other
|
return self.get_float() >= other
|
||||||
|
|
||||||
"""
|
#The following helper methods enable support for arithmetic operations on TimeTypes.
|
||||||
The following helper methods enable support for arithmetic operations on TimeTypes.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __set_float(self, num):
|
def set_float(self, num):
|
||||||
"""
|
"""
|
||||||
a helper method that takes a float and sets a TimeType's seconds and useconds fields.
|
a helper method that takes a float and sets a TimeType's seconds and useconds fields.
|
||||||
Note: This method is private because it is only used by the _get_type_from_float helper to
|
Note: This method is private because it is only used by the _get_type_from_float helper to
|
||||||
@ -402,84 +406,89 @@ class TimeType(type_base.BaseType):
|
|||||||
self.seconds = int(math.floor(num))
|
self.seconds = int(math.floor(num))
|
||||||
self.useconds = int(round((num - self.seconds) * 1000000))
|
self.useconds = int(round((num - self.seconds) * 1000000))
|
||||||
|
|
||||||
def __get_type_from_float(self, num):
|
def get_type_from_float(self, num):
|
||||||
"""
|
"""
|
||||||
a helper method that returns a new instance of TimeType and sets the seconds and useconds
|
a helper method that returns a new instance of TimeType and sets the seconds and useconds
|
||||||
fields using the given number. The new TimeType's time_base and time_context will be
|
fields using the given number. The new TimeType's time_base and time_context will be
|
||||||
preserved from the calling object.
|
preserved from the calling object.
|
||||||
"""
|
"""
|
||||||
tType = TimeType(self.__timeBase.val, self.__timeContext.val)
|
tType = TimeType(self.__timeBase.val, self.__timeContext.val)
|
||||||
tType.__set_float(num)
|
tType.set_float(num)
|
||||||
return tType
|
return tType
|
||||||
|
|
||||||
"""
|
#The following Python special methods add support for arithmetic operations on TimeTypes.
|
||||||
The following Python special methods add support for arithmetic operations on TimeTypes.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __add__(self, other):
|
def __add__(self, other):
|
||||||
|
""" Addition """
|
||||||
if isinstance(other, TimeType):
|
if isinstance(other, TimeType):
|
||||||
other = other.__get_float()
|
other = other.get_float()
|
||||||
num = self.__get_float() + other
|
num = self.get_float() + other
|
||||||
return self.__get_type_from_float(num)
|
return self.get_type_from_float(num)
|
||||||
|
|
||||||
def __sub__(self, other):
|
def __sub__(self, other):
|
||||||
|
""" Subtraction """
|
||||||
if isinstance(other, TimeType):
|
if isinstance(other, TimeType):
|
||||||
other = other.__get_float()
|
other = other.get_float()
|
||||||
num = self.__get_float() - other
|
num = self.get_float() - other
|
||||||
return self.__get_type_from_float(num)
|
return self.get_type_from_float(num)
|
||||||
|
|
||||||
def __mul__(self, other):
|
def __mul__(self, other):
|
||||||
|
""" Multiplication """
|
||||||
if isinstance(other, TimeType):
|
if isinstance(other, TimeType):
|
||||||
other = other.__get_float()
|
other = other.get_float()
|
||||||
num = self.__get_float() * other
|
num = self.get_float() * other
|
||||||
return self.__get_type_from_float(num)
|
return self.get_type_from_float(num)
|
||||||
|
|
||||||
def __truediv__(self, other):
|
def __truediv__(self, other):
|
||||||
|
""" True division """
|
||||||
if isinstance(other, TimeType):
|
if isinstance(other, TimeType):
|
||||||
other = other.__get_float()
|
other = other.get_float()
|
||||||
num = self.__get_float() / other
|
num = self.get_float() / other
|
||||||
return self.__get_type_from_float(num)
|
return self.get_type_from_float(num)
|
||||||
|
|
||||||
def __floordiv__(self, other):
|
def __floordiv__(self, other):
|
||||||
|
""" Floored divisionv """
|
||||||
if isinstance(other, TimeType):
|
if isinstance(other, TimeType):
|
||||||
other = other.__get_float()
|
other = other.get_float()
|
||||||
num = self.__get_float() // other
|
num = self.get_float() // other
|
||||||
return self.__get_type_from_float(num)
|
return self.get_type_from_float(num)
|
||||||
|
|
||||||
"""
|
#The following Python special methods add support for reflected arithmetic operations on TimeTypes.
|
||||||
The following Python special methods add support for reflected arithmetic operations on
|
|
||||||
TimeTypes.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __radd__(self, other):
|
def __radd__(self, other):
|
||||||
|
""" Reflected addition """
|
||||||
if isinstance(other, TimeType):
|
if isinstance(other, TimeType):
|
||||||
other = other.__get_float()
|
other = other.get_float()
|
||||||
num = other + self.__get_float()
|
num = other + self.get_float()
|
||||||
return self.__get_type_from_float(num)
|
return self.get_type_from_float(num)
|
||||||
|
|
||||||
def __rsub__(self, other):
|
def __rsub__(self, other):
|
||||||
|
""" Reflected subtraction """
|
||||||
if isinstance(other, TimeType):
|
if isinstance(other, TimeType):
|
||||||
other = other.__get_float()
|
other = other.get_float()
|
||||||
num = other - self.__get_float()
|
num = other - self.get_float()
|
||||||
return self.__get_type_from_float(num)
|
return self.get_type_from_float(num)
|
||||||
|
|
||||||
def __rmul__(self, other):
|
def __rmul__(self, other):
|
||||||
|
""" Reflected multiplication """
|
||||||
if isinstance(other, TimeType):
|
if isinstance(other, TimeType):
|
||||||
other = other.__get_float()
|
other = other.get_float()
|
||||||
num = other * self.__get_float()
|
num = other * self.get_float()
|
||||||
return self.__get_type_from_float(num)
|
return self.get_type_from_float(num)
|
||||||
|
|
||||||
def __rtruediv__(self, other):
|
def __rtruediv__(self, other):
|
||||||
|
""" Reflected division """
|
||||||
if isinstance(other, TimeType):
|
if isinstance(other, TimeType):
|
||||||
other = other.__get_float()
|
other = other.get_float()
|
||||||
num = other / self.__get_float()
|
num = other / self.get_float()
|
||||||
return self.__get_type_from_float(num)
|
return self.get_type_from_float(num)
|
||||||
|
|
||||||
def __rfloordiv__(self, other):
|
def __rfloordiv__(self, other):
|
||||||
|
""" Reflected floored division """
|
||||||
if isinstance(other, TimeType):
|
if isinstance(other, TimeType):
|
||||||
other = other.__get_float()
|
other = other.get_float()
|
||||||
num = other // self.__get_float()
|
num = other // self.get_float()
|
||||||
return self.__get_type_from_float(num)
|
return self.get_type_from_float(num)
|
||||||
|
|
||||||
|
|
||||||
def ser_deser_test(t_base, t_context, secs, usecs, should_err=False):
|
def ser_deser_test(t_base, t_context, secs, usecs, should_err=False):
|
||||||
@ -504,11 +513,11 @@ def ser_deser_test(t_base, t_context, secs, usecs, should_err=False):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
val = TimeType(t_base, t_context, secs, usecs)
|
val = TimeType(t_base, t_context, secs, usecs)
|
||||||
print(("creating: TimeType(%d, %d, %d, %d)" % (t_base, t_context, secs, usecs)))
|
print("creating: TimeType(%d, %d, %d, %d)" % (t_base, t_context, secs, usecs))
|
||||||
print((str(val)))
|
print(str(val))
|
||||||
|
|
||||||
buff = val.serialize()
|
buff = val.serialize()
|
||||||
print(("Serialized: %s" % repr(buff)))
|
print("Serialized: %s" % repr(buff))
|
||||||
type_base.showBytes(buff)
|
type_base.showBytes(buff)
|
||||||
|
|
||||||
val2 = TimeType()
|
val2 = TimeType()
|
||||||
|
|||||||
@ -6,9 +6,10 @@ Replaced type base class with decorators
|
|||||||
"""
|
"""
|
||||||
import abc
|
import abc
|
||||||
import struct
|
import struct
|
||||||
from .type_exceptions import AbstractMethodException
|
|
||||||
from .type_exceptions import DeserializeException
|
from .type_exceptions import (
|
||||||
from .type_exceptions import NotInitializedException
|
AbstractMethodException
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class BaseType(abc.ABC):
|
class BaseType(abc.ABC):
|
||||||
@ -21,10 +22,9 @@ class BaseType(abc.ABC):
|
|||||||
"""
|
"""
|
||||||
Serializes the current object type.
|
Serializes the current object type.
|
||||||
"""
|
"""
|
||||||
pass
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def deserialize(self, offset):
|
def deserialize(self, data, offset):
|
||||||
"""
|
"""
|
||||||
AbstractDeserialize interface
|
AbstractDeserialize interface
|
||||||
"""
|
"""
|
||||||
@ -39,14 +39,13 @@ class BaseType(abc.ABC):
|
|||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
""" Produces a string representation of a given type """
|
""" Produces a string representation of a given type """
|
||||||
return type(self).replace("Type", "")
|
return self.__class__.__name__.replace("Type", "")
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
def to_jsonable(self):
|
def to_jsonable(self):
|
||||||
"""
|
"""
|
||||||
Converts this type to a JSON serializable object
|
Converts this type to a JSON serializable object
|
||||||
"""
|
"""
|
||||||
if hasattr(self, "val"):
|
|
||||||
return {"value": self.val, "type": str(self)}
|
|
||||||
raise AbstractMethodException("to_jsonable")
|
raise AbstractMethodException("to_jsonable")
|
||||||
|
|
||||||
|
|
||||||
@ -55,6 +54,7 @@ class ValueType(BaseType, abc.ABC):
|
|||||||
An abstract base type used to represent a single value. This defines the value property, allowing for setting and
|
An abstract base type used to represent a single value. This defines the value property, allowing for setting and
|
||||||
reading from the .val member.
|
reading from the .val member.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, val=None):
|
def __init__(self, val=None):
|
||||||
""" Defines the single value """
|
""" Defines the single value """
|
||||||
self.__val = None
|
self.__val = None
|
||||||
@ -62,7 +62,6 @@ class ValueType(BaseType, abc.ABC):
|
|||||||
if val is not None:
|
if val is not None:
|
||||||
self.val = val
|
self.val = val
|
||||||
|
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def validate(self, val):
|
def validate(self, val):
|
||||||
"""
|
"""
|
||||||
@ -71,7 +70,6 @@ class ValueType(BaseType, abc.ABC):
|
|||||||
:param val: value to validate
|
:param val: value to validate
|
||||||
:raises TypeMismatchException: value has incorrect type, TypeRangeException: val is out of range
|
:raises TypeMismatchException: value has incorrect type, TypeRangeException: val is out of range
|
||||||
"""
|
"""
|
||||||
pass
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def val(self):
|
def val(self):
|
||||||
@ -84,66 +82,11 @@ class ValueType(BaseType, abc.ABC):
|
|||||||
self.validate(val)
|
self.validate(val)
|
||||||
self.__val = val
|
self.__val = val
|
||||||
|
|
||||||
|
def to_jsonable(self):
|
||||||
@abc.abstractmethod
|
|
||||||
@staticmethod
|
|
||||||
def get_serialize_format():
|
|
||||||
""" Gets the format serialization string such that the class can be serialized via struct """
|
|
||||||
|
|
||||||
def serialize(self):
|
|
||||||
""" Serializes this type using struct and the val property """
|
|
||||||
if self.val is None:
|
|
||||||
raise NotInitializedException(type(self))
|
|
||||||
return struct.pack(self.get_serialize_format(), self.val)
|
|
||||||
|
|
||||||
def deserialize(self, data, offset):
|
|
||||||
""" Serializes this type using struct and the val property """
|
|
||||||
try:
|
|
||||||
self.val = struct.unpack_from(self.get_serialize_format(), data, offset)[0]
|
|
||||||
except struct.error as err:
|
|
||||||
raise DeserializeException(str(err))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
#
|
|
||||||
def deserialize(Class):
|
|
||||||
"""
|
"""
|
||||||
Decorator adds common deserialize method
|
Converts this type to a JSON serializable object
|
||||||
"""
|
"""
|
||||||
setattr(Class, "__val", None)
|
return {"value": self.val, "type": str(self)}
|
||||||
|
|
||||||
def _deserialize(self, tformat, data, offset):
|
|
||||||
if offset > (len(data) - len(data[offset:])):
|
|
||||||
raise DeserializeException(
|
|
||||||
"Not enough data to deserialize! Needed: %d Left: %d"
|
|
||||||
% (self.getSize(), offset)
|
|
||||||
)
|
|
||||||
self.val = struct.unpack_from(tformat, data, offset)[0]
|
|
||||||
|
|
||||||
setattr(Class, "_deserialize", _deserialize)
|
|
||||||
|
|
||||||
return Class
|
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
#
|
|
||||||
def serialize(Class):
|
|
||||||
"""
|
|
||||||
Decorator adds common serialize method
|
|
||||||
"""
|
|
||||||
setattr(Class, "__val", None)
|
|
||||||
|
|
||||||
def _serialize(self, tformat, arg=None):
|
|
||||||
if self.val == None:
|
|
||||||
raise NotInitializedException(type(self))
|
|
||||||
if arg == None:
|
|
||||||
return struct.pack(tformat, self.val)
|
|
||||||
else:
|
|
||||||
return struct.pack(tformat, arg)
|
|
||||||
|
|
||||||
setattr(Class, "_serialize", _serialize)
|
|
||||||
return Class
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|||||||
@ -4,14 +4,13 @@ Created on Dec 18, 2014
|
|||||||
@author: tcanham
|
@author: tcanham
|
||||||
|
|
||||||
"""
|
"""
|
||||||
from __future__ import print_function
|
|
||||||
from __future__ import absolute_import
|
|
||||||
|
|
||||||
# Exception classes for all types
|
# Exception classes for all types
|
||||||
|
|
||||||
|
|
||||||
class TypeException(Exception):
|
class TypeException(Exception):
|
||||||
def __init__(self, val):
|
def __init__(self, val):
|
||||||
|
super().__init__(val)
|
||||||
self.except_msg = val
|
self.except_msg = val
|
||||||
|
|
||||||
def getMsg(self):
|
def getMsg(self):
|
||||||
@ -20,33 +19,31 @@ class TypeException(Exception):
|
|||||||
|
|
||||||
class AbstractMethodException(TypeException):
|
class AbstractMethodException(TypeException):
|
||||||
def __init__(self, val):
|
def __init__(self, val):
|
||||||
super(AbstractMethodException, self).__init__(
|
super().__init__("%s must be implemented since it is abstract!" % str(val))
|
||||||
"%s must be implemented since it is abstract!" % str(val)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class TypeRangeException(TypeException):
|
class TypeRangeException(TypeException):
|
||||||
def __init__(self, val):
|
def __init__(self, val):
|
||||||
super(TypeRangeException, self).__init__("Value %s out of range!" % str(val))
|
super().__init__("Value %s out of range!" % str(val))
|
||||||
|
|
||||||
|
|
||||||
class StringSizeException(TypeException):
|
class StringSizeException(TypeException):
|
||||||
def __init__(self, size, max_size):
|
def __init__(self, size, max_size):
|
||||||
super(StringSizeException, self).__init__(
|
super().__init__(
|
||||||
"String size %s is greater than %s!" % (str(size), str(max_size))
|
"String size {} is greater than {}!".format(str(size), str(max_size))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TypeMismatchException(TypeException):
|
class TypeMismatchException(TypeException):
|
||||||
def __init__(self, expected_type, actual_type):
|
def __init__(self, expected_type, actual_type):
|
||||||
super(TypeMismatchException, self).__init__(
|
super().__init__(
|
||||||
"Type %s expected, type %s found!" % (expected_type, actual_type)
|
"Type {} expected, type {} found!".format(expected_type, actual_type)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class ArrayLengthException(TypeException):
|
class ArrayLengthException(TypeException):
|
||||||
def __init__(self, arr_type, expected_len, actual_len):
|
def __init__(self, arr_type, expected_len, actual_len):
|
||||||
super(ArrayLengthException, self).__init__(
|
super().__init__(
|
||||||
"Array type %s is of length %s, actual length %s found!"
|
"Array type %s is of length %s, actual length %s found!"
|
||||||
% (arr_type, expected_len, actual_len)
|
% (arr_type, expected_len, actual_len)
|
||||||
)
|
)
|
||||||
@ -54,38 +51,35 @@ class ArrayLengthException(TypeException):
|
|||||||
|
|
||||||
class EnumMismatchException(TypeException):
|
class EnumMismatchException(TypeException):
|
||||||
def __init__(self, enum, bad_member):
|
def __init__(self, enum, bad_member):
|
||||||
super(EnumMismatchException, self).__init__(
|
super().__init__(
|
||||||
"Invalid enum member %s set in %s enum!" % (bad_member, enum)
|
"Invalid enum member {} set in {} enum!".format(bad_member, enum)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class DeserializeException(TypeException):
|
class DeserializeException(TypeException):
|
||||||
def __init__(self, message):
|
pass
|
||||||
super(DeserializeException, self).__init__(message)
|
|
||||||
|
|
||||||
|
|
||||||
class ArgNotFoundException(TypeException):
|
class ArgNotFoundException(TypeException):
|
||||||
def __init__(self, message):
|
def __init__(self, message):
|
||||||
super(ArgNotFoundException, self).__init__("Arg %s not found!" % message)
|
super().__init__("Arg %s not found!" % message)
|
||||||
|
|
||||||
|
|
||||||
class NotInitializedException(TypeException):
|
class NotInitializedException(TypeException):
|
||||||
def __init__(self, message):
|
def __init__(self, message):
|
||||||
super(NotInitializedException, self).__init__(
|
super().__init__("Instance %s not initialized!" % message)
|
||||||
"Instance %s not initialized!" % message
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class NotOverridenException(TypeException):
|
class NotOverridenException(TypeException):
|
||||||
def __init__(self, message):
|
def __init__(self, message):
|
||||||
super(NotOverridenException, self).__init__(
|
super().__init__(
|
||||||
"Required base class method not overrwritten in type %s!" % message
|
"Required base class method not overrwritten in type %s!" % message
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class ArgLengthMismatchException(TypeException):
|
class ArgLengthMismatchException(TypeException):
|
||||||
def __init__(self, arg_length_actual, arg_length_given):
|
def __init__(self, arg_length_actual, arg_length_given):
|
||||||
super(ArgLengthMismatchException, self).__init__(
|
super().__init__(
|
||||||
"%d args provided, but command expects %d args!"
|
"%d args provided, but command expects %d args!"
|
||||||
% (arg_length_given, arg_length_actual)
|
% (arg_length_given, arg_length_actual)
|
||||||
)
|
)
|
||||||
@ -93,7 +87,7 @@ class ArgLengthMismatchException(TypeException):
|
|||||||
|
|
||||||
class CompoundTypeLengthMismatchException(TypeException):
|
class CompoundTypeLengthMismatchException(TypeException):
|
||||||
def __init__(self, field_length_actual, field_length_given):
|
def __init__(self, field_length_actual, field_length_given):
|
||||||
super(CompoundTypeLengthMismatchException, self).__init__(
|
super().__init__(
|
||||||
"%d fields provided, but compound type expects %d fields!"
|
"%d fields provided, but compound type expects %d fields!"
|
||||||
% (field_length_given, field_length_actual)
|
% (field_length_given, field_length_actual)
|
||||||
)
|
)
|
||||||
|
|||||||
@ -7,28 +7,26 @@ receiver of these delegated functions.
|
|||||||
|
|
||||||
@author mstarch
|
@author mstarch
|
||||||
"""
|
"""
|
||||||
import io
|
|
||||||
import os
|
|
||||||
import re
|
|
||||||
import pty
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
import shutil
|
|
||||||
import tempfile
|
|
||||||
import subprocess
|
|
||||||
import itertools
|
|
||||||
import functools
|
|
||||||
import collections
|
|
||||||
import selectors
|
|
||||||
|
|
||||||
# Get a cache directory for building CMakeList file, if need and remove at exit
|
# Get a cache directory for building CMakeList file, if need and remove at exit
|
||||||
import atexit
|
import atexit
|
||||||
import six
|
import collections
|
||||||
|
import functools
|
||||||
|
import itertools
|
||||||
|
import os
|
||||||
|
import pty
|
||||||
|
import re
|
||||||
|
import selectors
|
||||||
|
import shutil
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import tempfile
|
||||||
|
import time
|
||||||
|
|
||||||
import fprime.fbuild
|
import fprime.fbuild
|
||||||
import fprime.fbuild.settings
|
import fprime.fbuild.settings
|
||||||
|
|
||||||
|
|
||||||
class CMakeBuildCache(object):
|
class CMakeBuildCache:
|
||||||
"""
|
"""
|
||||||
Builds CMake deployment for the purposes of inspecting that build. This exists because generating a build on every
|
Builds CMake deployment for the purposes of inspecting that build. This exists because generating a build on every
|
||||||
call take a long time. This cache will hold the results to prevent recalculation.
|
call take a long time. This cache will hold the results to prevent recalculation.
|
||||||
@ -64,7 +62,7 @@ class CMakeBuildCache(object):
|
|||||||
return self.tempdir
|
return self.tempdir
|
||||||
|
|
||||||
|
|
||||||
class CMakeHandler(object):
|
class CMakeHandler:
|
||||||
"""
|
"""
|
||||||
CMake handler interacts with an F prime CMake-based system. This will help us interact with CMake in refined ways.
|
CMake handler interacts with an F prime CMake-based system. This will help us interact with CMake in refined ways.
|
||||||
"""
|
"""
|
||||||
@ -156,11 +154,11 @@ class CMakeHandler(object):
|
|||||||
run_args + fleshed_args, write_override=True, environment=environment
|
run_args + fleshed_args, write_override=True, environment=environment
|
||||||
)
|
)
|
||||||
|
|
||||||
def find_hashed_file(self, build_dir, hash):
|
def find_hashed_file(self, build_dir, hash_value):
|
||||||
"""
|
"""
|
||||||
Find a file from a hash
|
Find a file from a hash
|
||||||
:param build_dir: build directory to search
|
:param build_dir: build directory to search
|
||||||
:param hash: hash number
|
:param hash_value: hash number
|
||||||
:return: filename
|
:return: filename
|
||||||
"""
|
"""
|
||||||
hashes_file = os.path.join(build_dir, "hashes.txt")
|
hashes_file = os.path.join(build_dir, "hashes.txt")
|
||||||
@ -168,9 +166,9 @@ class CMakeHandler(object):
|
|||||||
raise CMakeException(
|
raise CMakeException(
|
||||||
"Failed to find {}, was the build generated.".format(hashes_file)
|
"Failed to find {}, was the build generated.".format(hashes_file)
|
||||||
)
|
)
|
||||||
with open(hashes_file, "r") as file_handle:
|
with open(hashes_file) as file_handle:
|
||||||
lines = filter(
|
lines = filter(
|
||||||
lambda line: "{:x}".format(hash) in line, file_handle.readlines()
|
lambda line: "{:x}".format(hash_value) in line, file_handle.readlines()
|
||||||
)
|
)
|
||||||
return list(lines)
|
return list(lines)
|
||||||
|
|
||||||
@ -289,7 +287,7 @@ class CMakeHandler(object):
|
|||||||
:param cmake_dir: a cmake directory (project or build) to used. default: None, use existing temp cached build.
|
:param cmake_dir: a cmake directory (project or build) to used. default: None, use existing temp cached build.
|
||||||
:return: list of values, or Nones
|
:return: list of values, or Nones
|
||||||
"""
|
"""
|
||||||
if isinstance(fields, six.string_types):
|
if isinstance(fields, str):
|
||||||
fields = [fields]
|
fields = [fields]
|
||||||
# Setup the build_dir if it can be detected. Without a cache or specified value, we can crash
|
# Setup the build_dir if it can be detected. Without a cache or specified value, we can crash
|
||||||
build_dir = self._build_directory_from_cmake_dir(cmake_dir)
|
build_dir = self._build_directory_from_cmake_dir(cmake_dir)
|
||||||
@ -407,7 +405,7 @@ class CMakeHandler(object):
|
|||||||
if not os.path.isfile(cmake_file):
|
if not os.path.isfile(cmake_file):
|
||||||
raise CMakeProjectException(source_dir, "No CMakeLists.txt is defined")
|
raise CMakeProjectException(source_dir, "No CMakeLists.txt is defined")
|
||||||
# Test the cmake_file for project(
|
# Test the cmake_file for project(
|
||||||
with open(cmake_file, "r") as file_handle:
|
with open(cmake_file) as file_handle:
|
||||||
project_lines = list(
|
project_lines = list(
|
||||||
filter(lambda line: "project(" in line, file_handle.readlines())
|
filter(lambda line: "project(" in line, file_handle.readlines())
|
||||||
)
|
)
|
||||||
@ -491,10 +489,7 @@ class CMakeHandler(object):
|
|||||||
os.close(pty_out_w)
|
os.close(pty_out_w)
|
||||||
os.close(pty_err_w)
|
os.close(pty_err_w)
|
||||||
ret, stdout, stderr = self._communicate(
|
ret, stdout, stderr = self._communicate(
|
||||||
proc,
|
proc, open(pty_out_r, mode="rb"), open(pty_err_r, mode="rb"), print_output,
|
||||||
io.open(pty_out_r, mode="rb"),
|
|
||||||
io.open(pty_err_r, mode="rb"),
|
|
||||||
print_output,
|
|
||||||
)
|
)
|
||||||
# Raising an exception when the return code is non-zero allows us to handle the exception internally if it is
|
# Raising an exception when the return code is non-zero allows us to handle the exception internally if it is
|
||||||
# needed. Thus we do not just exit.
|
# needed. Thus we do not just exit.
|
||||||
@ -540,7 +535,7 @@ class CMakeHandler(object):
|
|||||||
line = key.fileobj.readline().decode().replace("\r\n", "\n")
|
line = key.fileobj.readline().decode().replace("\r\n", "\n")
|
||||||
# Some systems (like running inside Docker) raise an io error instead of returning "" when the device
|
# Some systems (like running inside Docker) raise an io error instead of returning "" when the device
|
||||||
# is ended. Not sure why this is, but the effect is the same, on IOError assume end-of-input
|
# is ended. Not sure why this is, but the effect is the same, on IOError assume end-of-input
|
||||||
except IOError:
|
except OSError:
|
||||||
line = ""
|
line = ""
|
||||||
appendable.append(line)
|
appendable.append(line)
|
||||||
# Streams are EOF when the line returned is empty. Once this occurs, we are responsible for closing the
|
# Streams are EOF when the line returned is empty. Once this occurs, we are responsible for closing the
|
||||||
@ -568,7 +563,7 @@ class CMakeInconsistencyException(CMakeException):
|
|||||||
|
|
||||||
def __init__(self, project_cmake, build_dir):
|
def __init__(self, project_cmake, build_dir):
|
||||||
""" Force an appropriate message """
|
""" Force an appropriate message """
|
||||||
super(CMakeInconsistencyException, self).__init__(
|
super().__init__(
|
||||||
"{} is inconsistent with build {}. Regenerate the build".format(
|
"{} is inconsistent with build {}. Regenerate the build".format(
|
||||||
project_cmake, build_dir
|
project_cmake, build_dir
|
||||||
)
|
)
|
||||||
@ -580,9 +575,7 @@ class CMakeOrphanException(CMakeException):
|
|||||||
|
|
||||||
def __init__(self, file_dir):
|
def __init__(self, file_dir):
|
||||||
""" Force an appropriate message """
|
""" Force an appropriate message """
|
||||||
super(CMakeOrphanException, self).__init__(
|
super().__init__("{} is outside the F prime project".format(file_dir))
|
||||||
"{} is outside the F prime project".format(file_dir)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class CMakeProjectException(CMakeException):
|
class CMakeProjectException(CMakeException):
|
||||||
@ -590,7 +583,7 @@ class CMakeProjectException(CMakeException):
|
|||||||
|
|
||||||
def __init__(self, project_dir, error):
|
def __init__(self, project_dir, error):
|
||||||
""" Force an appropriate message """
|
""" Force an appropriate message """
|
||||||
super(CMakeProjectException, self).__init__(
|
super().__init__(
|
||||||
"{} is an invalid F prime deployment. {}".format(project_dir, error)
|
"{} is an invalid F prime deployment. {}".format(project_dir, error)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -600,7 +593,7 @@ class CMakeInvalidBuildException(CMakeException):
|
|||||||
|
|
||||||
def __init__(self, build_dir):
|
def __init__(self, build_dir):
|
||||||
""" Force an appropriate message """
|
""" Force an appropriate message """
|
||||||
super(CMakeInvalidBuildException, self).__init__(
|
super().__init__(
|
||||||
"{} is not a CMake build directory. Please setup using 'fprime-util generate'".format(
|
"{} is not a CMake build directory. Please setup using 'fprime-util generate'".format(
|
||||||
build_dir
|
build_dir
|
||||||
)
|
)
|
||||||
@ -612,7 +605,7 @@ class CMakeExecutionException(CMakeException):
|
|||||||
|
|
||||||
def __init__(self, message, stderr, printed):
|
def __init__(self, message, stderr, printed):
|
||||||
""" The error data should be stored """
|
""" The error data should be stored """
|
||||||
super(CMakeExecutionException, self).__init__(message)
|
super().__init__(message)
|
||||||
self.stderr = stderr
|
self.stderr = stderr
|
||||||
self.need = not printed
|
self.need = not printed
|
||||||
|
|
||||||
@ -636,6 +629,4 @@ class CMakeNoSuchTargetException(CMakeException):
|
|||||||
|
|
||||||
def __init__(self, build_dir, target):
|
def __init__(self, build_dir, target):
|
||||||
""" Better messaging for this exception """
|
""" Better messaging for this exception """
|
||||||
super(CMakeNoSuchTargetException, self).__init__(
|
super().__init__("{} does not support target {}".format(build_dir, target))
|
||||||
"{} does not support target {}".format(build_dir, target)
|
|
||||||
)
|
|
||||||
|
|||||||
@ -6,8 +6,8 @@ settings from the settings.default file that is part of the F prime deployment d
|
|||||||
|
|
||||||
@author mstarch
|
@author mstarch
|
||||||
"""
|
"""
|
||||||
import os
|
|
||||||
import configparser # Written after PY2 eol
|
import configparser # Written after PY2 eol
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
class IniSettings:
|
class IniSettings:
|
||||||
@ -104,7 +104,7 @@ class IniSettings:
|
|||||||
config_dir = IniSettings.read_safe_path(
|
config_dir = IniSettings.read_safe_path(
|
||||||
confparse, "fprime", "config_directory", settings_file
|
confparse, "fprime", "config_directory", settings_file
|
||||||
)
|
)
|
||||||
config_dir = None if not config_dir else ac_consts[0]
|
config_dir = None if not config_dir else config_dir[0]
|
||||||
|
|
||||||
# Read separate environment file if necessary
|
# Read separate environment file if necessary
|
||||||
env_file = IniSettings.read_safe_path(
|
env_file = IniSettings.read_safe_path(
|
||||||
@ -158,10 +158,6 @@ class IniSettings:
|
|||||||
class FprimeLocationUnknownException(Exception):
|
class FprimeLocationUnknownException(Exception):
|
||||||
""" Fprime location could not be determined """
|
""" Fprime location could not be determined """
|
||||||
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class FprimeSettingsException(Exception):
|
class FprimeSettingsException(Exception):
|
||||||
""" An exception for handling F prime settings misconfiguration """
|
""" An exception for handling F prime settings misconfiguration """
|
||||||
|
|
||||||
pass
|
|
||||||
|
|||||||
@ -5,6 +5,7 @@ This acts as the main entry point for the fprime.util module. This allows users
|
|||||||
This will include the build_helper scripts and run them.
|
This will include the build_helper scripts and run them.
|
||||||
"""
|
"""
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import fprime.util.build_helper
|
import fprime.util.build_helper
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -13,15 +13,13 @@ are supported herein:
|
|||||||
|
|
||||||
@author mstarch
|
@author mstarch
|
||||||
"""
|
"""
|
||||||
from __future__ import print_function
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import argparse
|
import argparse
|
||||||
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
|
import sys
|
||||||
|
|
||||||
import fprime.fbuild
|
import fprime.fbuild
|
||||||
|
|
||||||
|
|
||||||
UT_SUFFIX = "-ut"
|
UT_SUFFIX = "-ut"
|
||||||
ACTION_MAP = {
|
ACTION_MAP = {
|
||||||
"generate": {
|
"generate": {
|
||||||
@ -248,6 +246,7 @@ def parse_args(args):
|
|||||||
cmake_args, make_args = validate(parsed)
|
cmake_args, make_args = validate(parsed)
|
||||||
return parsed, cmake_args, make_args, automatic_build_dir
|
return parsed, cmake_args, make_args, automatic_build_dir
|
||||||
|
|
||||||
|
|
||||||
def confirm():
|
def confirm():
|
||||||
"""
|
"""
|
||||||
Confirms the removal of the file with a yes or no input.
|
Confirms the removal of the file with a yes or no input.
|
||||||
@ -255,18 +254,12 @@ def confirm():
|
|||||||
"""
|
"""
|
||||||
# Loop "forever"
|
# Loop "forever"
|
||||||
while True:
|
while True:
|
||||||
# Py 2/3
|
confirm_input = input("Purge this directory (yes/no)?")
|
||||||
prompter = input
|
if confirm_input.lower() in ["y", "yes"]:
|
||||||
try:
|
|
||||||
prompter = raw_input
|
|
||||||
except NameError:
|
|
||||||
pass
|
|
||||||
confirm = prompter("Purge this directory (yes/no)?")
|
|
||||||
if confirm.lower() in ["y", "yes"]:
|
|
||||||
return True
|
return True
|
||||||
elif confirm.lower() in ["n", "no"]:
|
elif confirm_input.lower() in ["n", "no"]:
|
||||||
return False
|
return False
|
||||||
print("{} is invalid. Please use 'yes' or 'no'".format(confirm))
|
print("{} is invalid. Please use 'yes' or 'no'".format(confirm_input))
|
||||||
|
|
||||||
|
|
||||||
def purge_functionality(build_dir, force=False):
|
def purge_functionality(build_dir, force=False):
|
||||||
@ -323,7 +316,7 @@ def utility_entry(args=None):
|
|||||||
.format("automatic" if automatic_build_dir else "specified", parsed.build_dir + UT_SUFFIX))
|
.format("automatic" if automatic_build_dir else "specified", parsed.build_dir + UT_SUFFIX))
|
||||||
fprime.fbuild.builder().generate_build(parsed.path, parsed.build_dir + UT_SUFFIX, cmake_args)
|
fprime.fbuild.builder().generate_build(parsed.path, parsed.build_dir + UT_SUFFIX, cmake_args)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
print("[INFO] Error detected, automatically cleaning up failed-generation")
|
print("[INFO] Error detected, automatically cleaning up failed-generation. Error: {}".format(exc))
|
||||||
purge_functionality(parsed.build_dir, True)
|
purge_functionality(parsed.build_dir, True)
|
||||||
raise
|
raise
|
||||||
else:
|
else:
|
||||||
|
|||||||
@ -5,20 +5,26 @@ Created on Jun 25, 2020
|
|||||||
@author: hpaulson
|
@author: hpaulson
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import absolute_import
|
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from fprime.common.models.serialize import type_base
|
|
||||||
from fprime.common.models.serialize.bool_type import BoolType
|
from fprime.common.models.serialize.bool_type import BoolType
|
||||||
from fprime.common.models.serialize.enum_type import EnumType
|
from fprime.common.models.serialize.enum_type import EnumType
|
||||||
from fprime.common.models.serialize.numerical_types import I8Type, I16Type, I32Type, I64Type, U8Type, U16Type, U32Type, \
|
from fprime.common.models.serialize.numerical_types import (
|
||||||
U64Type, F32Type, F64Type
|
F32Type,
|
||||||
|
F64Type,
|
||||||
|
I8Type,
|
||||||
|
I16Type,
|
||||||
|
I32Type,
|
||||||
|
I64Type,
|
||||||
|
U8Type,
|
||||||
|
U16Type,
|
||||||
|
U32Type,
|
||||||
|
U64Type,
|
||||||
|
)
|
||||||
from fprime.common.models.serialize.serializable_type import SerializableType
|
from fprime.common.models.serialize.serializable_type import SerializableType
|
||||||
from fprime.common.models.serialize.string_type import StringType
|
from fprime.common.models.serialize.string_type import StringType
|
||||||
from fprime.common.models.serialize.time_type import TimeType
|
from fprime.common.models.serialize.time_type import TimeBase, TimeType, ser_deser_test
|
||||||
from fprime.common.models.serialize.time_type import TimeBase
|
|
||||||
from fprime.common.models.serialize.time_type import ser_deser_test
|
|
||||||
|
|
||||||
|
|
||||||
def test_bool_type():
|
def test_bool_type():
|
||||||
|
|||||||
@ -2,11 +2,12 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
|
from fprime.common.models.serialize.time_type import TimeType
|
||||||
|
|
||||||
filename = os.path.dirname(__file__)
|
filename = os.path.dirname(__file__)
|
||||||
fprime_path = os.path.join(filename, "../../../../../src")
|
fprime_path = os.path.join(filename, "../../../../../src")
|
||||||
sys.path.insert(0, fprime_path)
|
sys.path.insert(0, fprime_path)
|
||||||
|
|
||||||
from fprime.common.models.serialize.time_type import TimeType
|
|
||||||
|
|
||||||
class TimeTypeTestCases(unittest.TestCase):
|
class TimeTypeTestCases(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
|||||||
@ -7,10 +7,11 @@ that they function as expected.
|
|||||||
@author mstarch
|
@author mstarch
|
||||||
"""
|
"""
|
||||||
import os
|
import os
|
||||||
import pytest
|
|
||||||
import shutil
|
import shutil
|
||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
import fprime.fbuild
|
import fprime.fbuild
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user