2.0 RELEASE (candidate :)

- removed old garbage
- distutils
This commit is contained in:
Martinez 2017-10-10 00:26:52 +02:00
parent 76ab4c1d32
commit 3a8ae90597
11 changed files with 20 additions and 820 deletions

View file

@ -13,12 +13,3 @@ from . import misc
from . import text
from . import types
from . import version
print = text.Output("over.__init__", stream=sys.stderr)
core = aux.DeprecationForwarder(sys.modules[__name__], "over.core", "over")
textui = aux.DeprecationForwarder(text, "over.core.textui", "over.text")
#for module in [types]:
# if module.__file__[-2:] == "py":
# print("<r>unable to load C implementation<.> of <y>%s<.>, falling back to pure Python instead" %(module.__name__), print.tl.warn)

View file

View file

@ -1,50 +0,0 @@
#! /usr/bin/env python3
# encoding: utf-8
class compare_float:
"""
Sets .lt, .eq or .gt iff A is less than, equal or greather than B.
"""
def __init__(self, A, B, epsilon=1e-12):
self.A = A
self.B = B
self.epsilon = epsilon
self.lt = False
self.le = True
self.eq = False
self.ge = True
self.gt = False
self.ne = False
if A < (B - epsilon):
self.lt = True
self.ge = False
elif A > (B + epsilon):
self.gt = True
self.le = False
if abs(A - B) < epsilon:
self.eq = True
else:
self.ne = True
# convenience
self.less = self.lt
self.less_or_equal = self.le
self.equal = self.eq
self.greater_or_equal = self.ge
self.greater = self.gt
self.not_equal = self.ne
def __repr__(self):
return "compare_float(%.2f, %.2f, epsilon=%.03e)" %(self.A, self.B, self.epsilon)
if __name__ == '__main__':
x = compare_float(1, 2, 0.5)
assert x.lt and x.less and not (x.gt or x.ge)
x = compare_float(2, 2, 0.5)
assert x.eq and x.le and x.ge and not (x.lt or x.gt)
x = compare_float(3, 2, 0.5)
assert x.gt and x.ge and not (x.le or x.eq or x.lt)

View file

@ -1,470 +0,0 @@
#! /bin/env python3
# encoding: utf-8
"""
Vector and Matrix Math
"""
from libc.stdlib cimport malloc, realloc, free
from libc.stdint cimport uint8_t, uint16_t, uint64_t
from libc.math cimport sin, cos, sqrt
cdef class mat4:
"""
A float 4x4 matrix.
All arrays are column-major, i.e. OpenGL style:
0 4 8 12
1 5 9 13
2 6 10 14
3 7 11 15
The matrix implements stacking useful for graphics.
"""
def __cinit__(mat4 self):
to_alloc = 16 * sizeof(float)
self.stack = <float *>malloc(to_alloc)
if not self.stack:
raise MemoryError("Unable to malloc %d B for mat4." %(to_alloc))
self.m = self.stack
self.size = 1
def _debug(mat4 self):
print("--- self.stack = %d" %(<uint64_t>self.stack))
print("--- self.m = %d (+%d)" %(<uint64_t>self.m, self.m - self.stack))
print("--- self.size = %d" %(self.size))
def __init__(mat4 self, *args):
"""
Create a ma4t.
Accepts any number of parameters between 0 and 16 to fill the
matrix from the upper left corner going down (column-wise).
"""
length = len(args)
if length == 1 and isinstance(args[0], (list, tuple)):
args = args[0]
length = len(args)
if length > 16:
raise ValueError("Attempt to initialize a mat4 with %d arguments." %(length))
self.load_from(args)
def __dealloc__(mat4 self):
free(self.stack)
def __getstate__(mat4 self):
state = []
for i in range(self.m - self.stack + 16):
state.append(self.stack[i])
return state
def __setstate__(mat4 self, state):
length = len(state)
matrices = length//16
if not matrices*16 == length:
raise ValueError("mat4 __setstate__ got %d floats as a state" %(length))
self.m = self.stack
slot_full = False
for start in range(0, length, 16):
if slot_full:
self.push()
slot_full = False
self.load_from(state[start:start+16])
slot_full = True
def __getitem__(mat4 self, int i):
if i > 16 or i < 0:
raise IndexError("element index out of range(16)")
return self.m[i]
def __setitem__(self, int i, value):
if i > 16 or i < 0:
raise IndexError("element index out of range(16)")
self.m[i] = value
def push(mat4 self):
"""
Push the current matrix into the stack and load up an empty one (a zero matrix).
TODO consider copying the matrix instead?
"""
# self.m points to the current matrix
# self.stack points to the first matrix
# self.size how many matrices are allocated
# ensure there's room for one more
cdef unsigned int used = 1 + (self.m - self.stack) / 16
cdef unsigned int empty = self.size - used
cdef float *tmp
if not empty:
self.size += 1
to_alloc = self.size * 16 * sizeof(float)
tmp = <float *>realloc(self.stack, to_alloc)
if tmp:
self.stack = tmp
else:
raise MemoryError("Unable to malloc %d B for mat4." %(to_alloc))
# advance the pointer to the new one
self.m = self.stack + 16 * used
# at this point there"s at least enough space for one matrix
# copy the old matrix into the new one
cdef uint8_t i
cdef float *old_m = self.m - 16
for i in range(16):
self.m[i] = old_m[i]
def pop(mat4 self):
"""
Pop a matrix from the stack.
"""
if self.m == self.stack:
raise IndexError("pop from an empty stack")
self.m -= 16
def get_list(mat4 self):
L = []
for i in range(16):
L.append(self.m[i])
return L
def load_from(mat4 self, L):
"""
Fill the current matrix from a either a list of values, column-major,
or another matrix. This method doesn't modify the stack, only the
current matrix is read and modified.
If the number of values isn"t 16, it will be padded to 16 by zeros.
If it's larger, GeneralError will be raised.
"""
if isinstance(L, mat4):
L = L.get_list()
length = 16
else:
length = len(L)
if length > 16:
raise ValueError("supplied list is longer than 16")
for i in range(16):
if i < length:
self.m[i] = L[i]
else:
self.m[i] = 0.0
def zero(mat4 self):
"""
Fill the matrix with zeroes.
"""
for i in range(16):
self.m[i] = 0.0
def identity(mat4 self):
"""
Make the matrix an identity.
"""
self.zero()
self.m[0] = 1.0
self.m[5] = 1.0
self.m[10] = 1.0
self.m[15] = 1.0
def transpose(mat4 self):
"""
Transpose the matrix.
"""
cdef float tmp
tmp = self.m[1]
self.m[1] = self.m[4]
self.m[4] = tmp
tmp = self.m[2]
self.m[2] = self.m[8]
self.m[8] = tmp
tmp = self.m[3]
self.m[3] = self.m[12]
self.m[12] = tmp
tmp = self.m[7]
self.m[7] = self.m[13]
self.m[13] = tmp
tmp = self.m[11]
self.m[11] = self.m[14]
self.m[14] = tmp
tmp = self.m[6]
self.m[6] = self.m[9]
self.m[9] = tmp
def invert(mat4 self):
"""
Invert the matrix.
"""
cdef float tmp[16]
cdef float det
tmp[0] = self.m[5]*self.m[10]*self.m[15] - self.m[5]*self.m[11]*self.m[14] - self.m[9]*self.m[6]*self.m[15] + self.m[9]*self.m[7]*self.m[14] + self.m[13]*self.m[6]*self.m[11] - self.m[13]*self.m[7]*self.m[10]
tmp[4] = -self.m[4]*self.m[10]*self.m[15] + self.m[4]*self.m[11]*self.m[14] + self.m[8]*self.m[6]*self.m[15] - self.m[8]*self.m[7]*self.m[14] - self.m[12]*self.m[6]*self.m[11] + self.m[12]*self.m[7]*self.m[10]
tmp[8] = self.m[4]*self.m[9]*self.m[15] - self.m[4]*self.m[11]*self.m[13] - self.m[8]*self.m[5]*self.m[15] + self.m[8]*self.m[7]*self.m[13] + self.m[12]*self.m[5]*self.m[11] - self.m[12]*self.m[7]*self.m[9]
tmp[12] = -self.m[4]*self.m[9]*self.m[14] + self.m[4]*self.m[10]*self.m[13] + self.m[8]*self.m[5]*self.m[14] - self.m[8]*self.m[6]*self.m[13] - self.m[12]*self.m[5]*self.m[10] + self.m[12]*self.m[6]*self.m[9]
det = self.m[0]*tmp[0] + self.m[1]*tmp[4] + self.m[2]*tmp[8] + self.m[3]*tmp[12]
# epsilon pulled straight out of Uranus
if det < 0.00005 and det > -0.00005:
print("det=%.1f" %(det))
return
tmp[1] = -self.m[1]*self.m[10]*self.m[15] + self.m[1]*self.m[11]*self.m[14] + self.m[9]*self.m[2]*self.m[15] - self.m[9]*self.m[3]*self.m[14] - self.m[13]*self.m[2]*self.m[11] + self.m[13]*self.m[3]*self.m[10]
tmp[5] = self.m[0]*self.m[10]*self.m[15] - self.m[0]*self.m[11]*self.m[14] - self.m[8]*self.m[2]*self.m[15] + self.m[8]*self.m[3]*self.m[14] + self.m[12]*self.m[2]*self.m[11] - self.m[12]*self.m[3]*self.m[10]
tmp[9] = -self.m[0]*self.m[9]*self.m[15] + self.m[0]*self.m[11]*self.m[13] + self.m[8]*self.m[1]*self.m[15] - self.m[8]*self.m[3]*self.m[13] - self.m[12]*self.m[1]*self.m[11] + self.m[12]*self.m[3]*self.m[9]
tmp[13] = self.m[0]*self.m[9]*self.m[14] - self.m[0]*self.m[10]*self.m[13] - self.m[8]*self.m[1]*self.m[14] + self.m[8]*self.m[2]*self.m[13] + self.m[12]*self.m[1]*self.m[10] - self.m[12]*self.m[2]*self.m[9]
tmp[2] = self.m[1]*self.m[6]*self.m[15] - self.m[1]*self.m[7]*self.m[14] - self.m[5]*self.m[2]*self.m[15] + self.m[5]*self.m[3]*self.m[14] + self.m[13]*self.m[2]*self.m[7] - self.m[13]*self.m[3]*self.m[6]
tmp[6] = -self.m[0]*self.m[6]*self.m[15] + self.m[0]*self.m[7]*self.m[14] + self.m[4]*self.m[2]*self.m[15] - self.m[4]*self.m[3]*self.m[14] - self.m[12]*self.m[2]*self.m[7] + self.m[12]*self.m[3]*self.m[6]
tmp[10] = self.m[0]*self.m[5]*self.m[15] - self.m[0]*self.m[7]*self.m[13] - self.m[4]*self.m[1]*self.m[15] + self.m[4]*self.m[3]*self.m[13] + self.m[12]*self.m[1]*self.m[7] - self.m[12]*self.m[3]*self.m[5]
tmp[14] = -self.m[0]*self.m[5]*self.m[14] + self.m[0]*self.m[6]*self.m[13] + self.m[4]*self.m[1]*self.m[14] - self.m[4]*self.m[2]*self.m[13] - self.m[12]*self.m[1]*self.m[6] + self.m[12]*self.m[2]*self.m[5]
tmp[3] = -self.m[1]*self.m[6]*self.m[11] + self.m[1]*self.m[7]*self.m[10] + self.m[5]*self.m[2]*self.m[11] - self.m[5]*self.m[3]*self.m[10] - self.m[9]*self.m[2]*self.m[7] + self.m[9]*self.m[3]*self.m[6]
tmp[7] = self.m[0]*self.m[6]*self.m[11] - self.m[0]*self.m[7]*self.m[10] - self.m[4]*self.m[2]*self.m[11] + self.m[4]*self.m[3]*self.m[10] + self.m[8]*self.m[2]*self.m[7] - self.m[8]*self.m[3]*self.m[6]
tmp[11] = -self.m[0]*self.m[5]*self.m[11] + self.m[0]*self.m[7]*self.m[9] + self.m[4]*self.m[1]*self.m[11] - self.m[4]*self.m[3]*self.m[9] - self.m[8]*self.m[1]*self.m[7] + self.m[8]*self.m[3]*self.m[5]
tmp[15] = self.m[0]*self.m[5]*self.m[10] - self.m[0]*self.m[6]*self.m[9] - self.m[4]*self.m[1]*self.m[10] + self.m[4]*self.m[2]*self.m[9] + self.m[8]*self.m[1]*self.m[6] - self.m[8]*self.m[2]*self.m[5]
det = 1.0 / det
self.m[0] = tmp[0] * det
self.m[1] = tmp[1] * det
self.m[2] = tmp[2] * det
self.m[3] = tmp[3] * det
self.m[4] = tmp[4] * det
self.m[5] = tmp[5] * det
self.m[6] = tmp[6] * det
self.m[7] = tmp[7] * det
self.m[8] = tmp[8] * det
self.m[9] = tmp[9] * det
self.m[10] = tmp[10] * det
self.m[11] = tmp[11] * det
self.m[12] = tmp[12] * det
self.m[13] = tmp[13] * det
self.m[14] = tmp[14] * det
self.m[15] = tmp[15] * det
def mulm(mat4 self, mat4 B, bint inplace=False):
"""
Return a matrix that is the result of multiplying this matrix by another.
M = self * mat4 B
"""
cdef uint8_t i
cdef mat4 tmp = mat4()
tmp.m[0] = self.m[0] * B.m[0] + self.m[4] * B.m[1] + self.m[8] * B.m[2] + self.m[12] * B.m[3]
tmp.m[1] = self.m[1] * B.m[0] + self.m[5] * B.m[1] + self.m[9] * B.m[2] + self.m[13] * B.m[3]
tmp.m[2] = self.m[2] * B.m[0] + self.m[6] * B.m[1] + self.m[10] * B.m[2] + self.m[14] * B.m[3]
tmp.m[3] = self.m[3] * B.m[0] + self.m[7] * B.m[1] + self.m[11] * B.m[2] + self.m[15] * B.m[3]
tmp.m[4] = self.m[0] * B.m[4] + self.m[4] * B.m[5] + self.m[8] * B.m[6] + self.m[12] * B.m[7]
tmp.m[5] = self.m[1] * B.m[4] + self.m[5] * B.m[5] + self.m[9] * B.m[6] + self.m[13] * B.m[7]
tmp.m[6] = self.m[2] * B.m[4] + self.m[6] * B.m[5] + self.m[10] * B.m[6] + self.m[14] * B.m[7]
tmp.m[7] = self.m[3] * B.m[4] + self.m[7] * B.m[5] + self.m[11] * B.m[6] + self.m[15] * B.m[7]
tmp.m[8] = self.m[0] * B.m[8] + self.m[4] * B.m[9] + self.m[8] * B.m[10] + self.m[12] * B.m[11]
tmp.m[9] = self.m[1] * B.m[8] + self.m[5] * B.m[9] + self.m[9] * B.m[10] + self.m[13] * B.m[11]
tmp.m[10] = self.m[2] * B.m[8] + self.m[6] * B.m[9] + self.m[10] * B.m[10] + self.m[14] * B.m[11]
tmp.m[11] = self.m[3] * B.m[8] + self.m[7] * B.m[9] + self.m[11] * B.m[10] + self.m[15] * B.m[11]
tmp.m[12] = self.m[0] * B.m[12] + self.m[4] * B.m[13] + self.m[8] * B.m[14] + self.m[12] * B.m[15]
tmp.m[13] = self.m[1] * B.m[12] + self.m[5] * B.m[13] + self.m[9] * B.m[14] + self.m[13] * B.m[15]
tmp.m[14] = self.m[2] * B.m[12] + self.m[6] * B.m[13] + self.m[10] * B.m[14] + self.m[14] * B.m[15]
tmp.m[15] = self.m[3] * B.m[12] + self.m[7] * B.m[13] + self.m[11] * B.m[14] + self.m[15] * B.m[15]
if inplace:
for i in range(16):
self.m[i] = tmp.m[i]
else:
return tmp
def mulv(mat4 self, vec3 v):
"""
Return a vec3 that is the result of multiplying this matrix by a vec3.
u = self * v
"""
cdef mat4 tmp = vec3()
tmp.v[0] = v.v[0]*self.m[0] + v.v[1]*self.m[4] + v.v[2]*self.m[8] + self.m[12]
tmp.v[1] = v.v[0]*self.m[1] + v.v[1]*self.m[5] + v.v[2]*self.m[9] + self.m[13]
tmp.v[2] = v.v[0]*self.m[2] + v.v[1]*self.m[6] + v.v[2]*self.m[10] + self.m[14]
return tmp
def mulf(mat4 self, f):
"""
Return a matrix that is the result of multiplying this matrix by a scalar.
M = self * f
"""
cdef mat4 tmp = mat4()
cdef int i
for i in range(16):
tmp.m[i] = self.m[i] * f
return tmp
def __repr__(mat4 self):
lines = []
lines.append("mat4(%.1f %.1f %.1f %.1f" %(self.m[0], self.m[4], self.m[8], self.m[12]))
lines.append(" %.1f %.1f %.1f %.1f" %(self.m[1], self.m[5], self.m[9], self.m[13]))
lines.append(" %.1f %.1f %.1f %.1f" %(self.m[2], self.m[6], self.m[10], self.m[14]))
lines.append(" %.1f %.1f %.1f %.1f)" %(self.m[3], self.m[7], self.m[11], self.m[15]))
return "\n".join(lines)
cdef class vec3:
"""
A float 3D vector.
>>> v = vec3(1, 1, 0)
>>> w = vec3(0, 1, 1)
>>> v.length
1.4142135623730951
>>> v.dot(w)
1.0
>>> v.cross(w)
vec4(1.00, 1.00, 1.00)
>>> v + w
vec4(1.00, 2.00, 1.00)
>>> w - v
vec4(-1.00, 0.00, 1.00)
"""
def __init__(vec3 self, *args):
"""
Create a vec3.
Accepts any number of parameters between 0 and 3 to fill the vector from the left.
"""
length = len(args)
if length == 1 and isinstance(args[0], (list, tuple)):
args = args[0]
length = len(args)
if length > 3:
raise ValueError("Attempt to initialize a vec3 with %d arguments." %(length))
for i in range(3):
if i < length:
self.v[i] = args[i]
else:
self.v[i] = 0.0
def __getitem__(vec3 self, int i):
if i >= 3 or i < 0:
raise IndexError("element index out of range(3)")
return self.v[i]
def __setitem__(vec3 self, int i, float value):
if i >= 3 or i < 0:
raise IndexError("element index out of range(3)")
self.v[i] = value
def __repr__(vec3 self):
return "vec3(%.2f, %.2f, %.2f)" %(self.v[0], self.v[1], self.v[2])
def __getstate__(vec3 self):
return (self.v[0], self.v[1], self.v[2])
def __setstate__(vec3 self, state):
self.v[0] = state[0]
self.v[1] = state[1]
self.v[2] = state[2]
@property
def length(vec3 self):
"""
Contains the geometric length of the vector.
"""
return sqrt(self.v[0]**2 + self.v[1]**2 + self.v[2]**2)
def normalized(vec3 self):
"""
Returns this vector, normalized.
"""
length = self.length
return vec3(self.v[0] / length, self.v[1] / length, self.v[2] / length)
def __add__(vec3 L, vec3 R):
return vec3(L.v[0] + R.v[0], L.v[1] + R.v[1], L.v[2] + R.v[2])
def __sub__(vec3 L, vec3 R):
return vec3(L.v[0] - R.v[0], L.v[1] - R.v[1], L.v[2] - R.v[2])
def __neg__(vec3 self):
return vec3(-self.v[0], -self.v[1], -self.v[2])
def dot(vec3 L, vec3 R):
"""
Returns the dot product of the two vectors.
E.g. u.dot(v) -> u . v
"""
return L.v[0] * R.v[0] + L.v[1] * R.v[1] + L.v[2] * R.v[2]
def cross(vec3 L, vec3 R):
"""
Returns the cross product of the two vectors.
E.g. u.cross(v) -> u x v
"""
return vec3(L.v[1]*R.v[2] - L.v[2]*R.v[1], L.v[0]*R.v[2] - L.v[2]*R.v[0], L.v[0]*R.v[1] - L.v[1]*R.v[0])
def __mul__(vec3 L, R):
"""
Multiplication of a vec3 by a float.
The float has to be on the right.
"""
return vec3(L.v[0] * R, L.v[1] * R, L.v[2] * R)

View file

@ -1,195 +0,0 @@
#! /usr/bin/env python3
# encoding: utf-8
import time
import serial
from .. import text
"""
OverTalk protocol spec
======================
Transport layer
---------------
TODO: Swap checksum and payload.
frame = [ 0x2a | destination (1) | source (1) | payload length (1) | payload (n) | checksum (1) ]
Any time a 0x2a is encountered the parser should flush its state and begin reading a new frame.
Bytes 0x2a, 0x2b, 0x11 and 0x13 are prefixed with 0x2b and inverted (XORed with 0xff) to avoid collisions.
Frames with destinations unknown to an OverShell are sent to the default interface, or dropped if
that's the interface they came from.
Command layer
-------------
NOTE: This is going to change.
Payload consists of one or more commands:
get_command = [ 0x00 | register (1) | target register (1) ]
set_command = [ 0x01 | register (1) | length (1) | value (n) ]
With a get_command the sender requests the receiver to read its own `register` and issue
a set_command that sets the sender's `target register` to that value.
A set_command does what is says on the box.
"""
class Transport:
"""
OverTalk Transport layer implementation.
Reads data from multiple interfaces and either routes frames or receives them.
A received frame is then made available via a public attribute.
Interfaces are objects that implement methods read() (returns one byte of data as int), write(buffer, len),
and waiting property (contains number of bytes waiting).
"""
def __init__(self, my_id, interfaces, def_route):
"""
@param my_id OverTalk address of this Transport instance
@param interfaces a dict of interfaces keyed by their IDs
@param def_route ID of default interface for sending
"""
assert my_id not in interfaces
assert def_route in interfaces
self.print = text.Output("over.serial.Transport")
self.my_id = my_id
self.def_route = def_route
self.interfaces = interfaces
self.destination_unknown = 0
self.incoming = None
self.print("on-line", text.Output.tl.done)
def update(self):
self.incoming = None
for interface_id, interface in self.interfaces.items():
if interface.waiting:
interface.last_data_received = time.time()
byte = interface.read()
if byte == 0x2a:
interface.rxbuffer = []
interface.reading_escape = False
interface.reading_frame = True
if byte == 0x2b:
interface.reading_escape = True
continue
if interface.reading_escape:
byte ^= 0xff
interface.reading_escape = False
if interface.reading_frame:
interface.rxbuffer.append(byte)
if self.verify_frame(interface):
self.process_frame(interface_id, interface.rxbuffer)
interface.rxbuffer = []
def verify_frame(self, interface):
buffer_length = len(interface.rxbuffer)
if buffer_length >= 4:
# at this point we can read frame"s declared size
if buffer_length >= interface.rxbuffer[3] + 5: # header (4) + payload + checksum (1)
# a frame has been read, huzzah!
interface.reading_frame = False
# checksum
if sum(interface.rxbuffer[:-1]) % 0x100 == interface.rxbuffer[-1]:
return True
else:
interface.malformed_frames += 1
self.print("broken frame received: §r§%s§.§" %(interface.rxbuffer))
interface.rxbuffer = []
return False
def escape_frame(self, frame):
assert frame[0] == 0x2a
frame_escaped = [0x2a]
for byte in frame[1:]:
if byte in (0x2a, 0x2b, 0x11, 0x13):
frame_escaped.append(0x2b)
byte ^= 0xff
frame_escaped.append(byte)
return frame_escaped
def process_frame(self, source_interface_id, frame):
payload = frame[4:-1]
destination = frame[1]
if destination == self.my_id:
self.incoming = (frame[2], payload)
else:
if destination in self.interfaces:
self.print("routing frame to [%d]" %(destination))
self.interfaces[destination].write(self.escape_frame(frame))
else:
if source_interface_id == self.def_route:
self.destination_unknown += 1
self.print("unknown destination <r>%d<.> for frame: <y>%s<.>" %(destination,
repr(frame)), text.Output.tl.fail)
else:
self.print("routing frame to default route [%d]" %(self.def_route))
self.interfaces[self.def_route].write(self.escape_frame(frame))
def send_data(self, destination, data):
frame = [0x2a, destination, self.my_id, len(data)] + list(data)
frame.append(sum(frame) % 0x100)
frame = self.escape_frame(frame)
if destination in self.interfaces:
s = self.interfaces[destination]
else:
s = self.interfaces[self.def_route]
s.write(frame)
class TTL_Interface:
def __init__(self, interface="/dev/ttyUSB0", baudrate=57600):
try:
self.s = serial.Serial(interface, baudrate, timeout=1)
except serial.serialutil.SerialException:
self.s = None
self.rxbuffer = []
self.reading_escape = False
self.reading_frame = False
self.malformed_frames = 0
self.last_data_received = 0
@property
def waiting(self):
if self.s:
return self.s.inWaiting()
else:
return 0
def read(self):
if self.s:
return ord(self.s.read())
else:
return 0
def write(self, data):
print("Sending:", "".join([hex(x)[2:].zfill(2) for x in data]))
if self.s:
self.s.write(bytes(data))

View file

@ -1,14 +0,0 @@
#! /bin/zsh
# encoding: utf-8
if [[ -a ".over_inhibit_deployment" ]]; then
echo '!! deployment inhibited by lock file (hint: run this from the target directory, not the over directory)'
elif [[ -n "$1" ]]; then
OVER_DIR="$(readlink -f "$(dirname "$0")")"
ln -s "$OVER_DIR"
cp "$OVER_DIR/template.py" "$1"
chmod +x "$1"
echo "over\n__pycache__" >> .gitignore
else
echo '!! Missing argument (program name).'
fi

View file

@ -1,36 +0,0 @@
#! /usr/bin/env python3
# encoding: utf-8
from collections import OrderedDict
# --------------------------------------------------
cdef class ndict(OrderedDict):
"""
An OrderedDict subclass whose keys are exposed as attributes.
>>> d = ndict()
>>> d.alpha = 1
>>> d["alpha"]
1
>>> d["beta"] = 42
>>> d.beta
42
>>> d
{"alpha": 1, "beta": 42}
"""
def __getattr__(self, str name):
"""
@while looking up an attribute
"""
if name in self:
return self[name]
elif name.replace("_", "-") in self:
return self[name.replace("_", "-")]
else:
raise AttributeError('"ndict" object has no attribute "%s"' %(name))
def __setattr__(self, str name, value):
self[name] = value

View file

@ -1,8 +1,8 @@
#! /usr/bin/env python3
# encoding: utf-8
major = 1 # VERSION_MAJOR_IDENTIFIER
minor = 101 # VERSION_MINOR_IDENTIFIER
# VERSION_LAST_MM 1.101
patch = 2 # VERSION_PATCH_IDENTIFIER
str = "1.101.2" # VERSION_STRING_IDENTIFIER
major = 2 # VERSION_MAJOR_IDENTIFIER
minor = 0 # VERSION_MINOR_IDENTIFIER
# VERSION_LAST_MM 2.0
patch = 0 # VERSION_PATCH_IDENTIFIER
str = "2.0.0" # VERSION_STRING_IDENTIFIER

View file

@ -0,0 +1,15 @@
from distutils.core import setup
setup(
name="over",
version="2.0.0",
author="Aggregate",
packages=["over"],
url="https://git.covalent.cz/overwatch/over/",
license="LICENSE.txt",
description="Useful libraries derived from the Overwatch UAV.",
install_requires=[
"pytz >= 2017.2",
"tzlocal >= 1.2"
]
)

41
test.py
View file

@ -1,41 +0,0 @@
#! /usr/bin/env python3
# encoding: utf-8
# library imports
import over
# local imports
import version
# --------------------------------------------------
# Exceptions
class ConfigurationError(Exception):
pass
# --------------------------------------------------
# Functions
# --------------------------------------------------
# Classes
# --------------------------------------------------
def noop(*args):
return args
def int4(*args):
return [int(x) for x in args]
if __name__ == "__main__":
main = over.app.Main("new-over-test", version.str, "LICENSE", features={"config_file": True})
# name, description, callback, default=Option_sources.none, count=0, overwrite=True, abbr=None, in_cfg_file=True, show_in_help=True
main.add_option("boolean-single", "ISO 8601 date for a new transfer (valid with +EHMU), defaults to current date. It's also used for relative times with --analysis-timeframe. You can use a day-count relative to today here.", over.callback.boolean, [False], abbr="1")
main.add_option("boolean-triple", "", over.callback.booleans, [False, False, False], abbr="3", count=3)
main.add_option("str-single", "", str, ["kek"], abbr="s", count=1)
main.add_option("str-quad", "", noop, ["ze", "kek", "is", "bek"], abbr="4", count=4)
main.add_option("int-quad", "", int4, [45, 72, 97, 18], abbr="i", count=4)
main.add_option("int-quad-multi", "", int4, [45, 72, 97, 18], abbr="I", count=4, overwrite=False)
main.add_doc("Description", ["What it does.", "Another paragraph."])
main.add_doc("Moar", ["When we launched Raspberry Pi Zero last November, its fair to say we were <W>blindsided<.> by the level of demand. We immediately sold every copy of MagPi issue 40 and every Zero in stock at our distributors; and every time a new batch of Zeros came through from the factory theyd sell out in minutes. To complicate matters, Zero then had to compete for factory space with Raspberry Pi 3, which was ramping for launch at the end of February.", "To connect the camera to the Zero, we offer a custom six-inch adapter cable. This converts from the fine-pitch connector format to the coarser pitch used by the camera board. Liz has a great picture of Mooncake, the official Raspberry Pi cat, attempting to eat the camera cable. She wont let me use it in this post so that you arent distracted from the pictures of the new Zero itself. Ive a feeling shell be tweeting it later today."])
main.setup()