def test_dump_lines(logger): """ """ raw_bytes = b'' point_data_fragment = [ # line: # # brush type ( struct.pack(BrushType.fmt, BrushType.REVERSE['pen']), BrushType.REVERSE['pen'], ), # colour (struct.pack(Colour.fmt, Colour.REVERSE['black']), Colour.REVERSE['black']), # magical unknown line attribute 1 (struct.pack(LineAttribute1.fmt, 0), 0), # base brush size (struct.pack(BrushBaseSize.fmt, BrushBaseSize.REVERSE['small']), BrushBaseSize.REVERSE['small']), # one point: (struct.pack(Points.fmt, 1), 1), # the single point's data: (struct.pack(X.fmt, 12.341), 12.341), (struct.pack(Y.fmt, 107.301), 107.301), (struct.pack(Pressure.fmt, 0.351), 0.351), (struct.pack(RotX.fmt, 0.03), 0.03), (struct.pack(RotY.fmt, 0.216), 0.216), ] for data in point_data_fragment: raw_bytes += data[0] # Set up the generator with the raw bytes: position = recover(raw_bytes) data = next(position) assert data == '' raw_bytes = Line.load(position).dump() position = recover(raw_bytes) next(position) the_line = Line.load(position) assert the_line.brush_type.name == 'pen' assert the_line.colour.name == 'black' assert the_line.line_attribute1.value == 0 assert the_line.brush_base_size.name == 'small' assert the_line.points.count == 1 result = the_line.points.points[0] assert round(result.x, 3) == 12.341 assert round(result.y, 3) == 107.301 assert round(result.pressure, 3) == 0.351 assert round(result.rot_x, 3) == 0.03 assert round(result.rot_y, 3) == 0.216
def test_point_parse(logger): """Verify Point.load from raw bytes. """ raw_bytes = b'' point_data_fragment = [ (struct.pack(lines.X.fmt, 12.341), 12.341), (struct.pack(lines.Y.fmt, 107.301), 107.301), (struct.pack(lines.Pressure.fmt, 0.351), 0.351), (struct.pack(lines.RotX.fmt, 0.03), 0.03), (struct.pack(lines.RotY.fmt, 0.216), 0.216), ] for data in point_data_fragment: raw_bytes += data[0] # Set up the generator with the raw bytes: position = recover(raw_bytes) data = next(position) assert data == '' result = lines.Point.load(position) assert round(result.x, 3) == 12.341 assert round(result.y, 3) == 107.301 assert round(result.pressure, 3) == 0.351 assert round(result.rot_x, 3) == 0.03 assert round(result.rot_y, 3) == 0.216
def test_points_class_parse(logger): """Verify Points class.load which creates individual Point instances from raw bytes. """ raw_bytes = b'' point_data_fragment = [ # one point: (struct.pack(lines.Points.fmt, 1), 1), # the single point's data: (struct.pack(lines.X.fmt, 12.341), 12.341), (struct.pack(lines.Y.fmt, 107.301), 107.301), (struct.pack(lines.Pressure.fmt, 0.351), 0.351), (struct.pack(lines.RotX.fmt, 0.03), 0.03), (struct.pack(lines.RotY.fmt, 0.216), 0.216), ] for data in point_data_fragment: raw_bytes += data[0] # Set up the generator with the raw bytes: position = recover(raw_bytes) data = next(position) assert data == '' result = lines.Points.load(position) assert result.count == 1 assert len(result.points) == 1 result = result.points[0] assert round(result.x, 3) == 12.341 assert round(result.y, 3) == 107.301 assert round(result.pressure, 3) == 0.351 assert round(result.rot_x, 3) == 0.03 assert round(result.rot_y, 3) == 0.216
def load(cls, raw_bytes): """Convert the raw bytes in a NotebookLines instance. :param raw_bytes: A bytes string. The raw_bytes will usually have come from the <document_id>.lines file. """ position = recover(raw_bytes) # Start the generator off at position 0 ready to extract the file # header. next(position) # recover the header file_header = FileHeader.load(position) assert file_header.header == FileHeader.EXPECTED # Now recover all the pages contained content: pages = Pages.load(position) notebook = NotebookLines(file_header, pages) position.close() return notebook
def test_lines_class_parse(logger): """Verify Lines class.load which creates an individual line instances from raw bytes. """ raw_bytes = b'' point_data_fragment = [ # Only 1 line in this "data" ( struct.pack(lines.Lines.fmt, 1), 1, ), # line: # # brush type ( struct.pack(lines.BrushType.fmt, lines.BrushType.REVERSE['pen']), lines.BrushType.REVERSE['pen'], ), # colour (struct.pack(lines.Colour.fmt, lines.Colour.REVERSE['black']), lines.Colour.REVERSE['black']), # magical unknown line attribute 1 (struct.pack(lines.LineAttribute1.fmt, 0), 0), # base brush size (struct.pack(lines.BrushBaseSize.fmt, lines.BrushBaseSize.REVERSE['small']), lines.BrushBaseSize.REVERSE['small']), # one point: (struct.pack(lines.Points.fmt, 1), 1), # the single point's data: (struct.pack(lines.X.fmt, 12.341), 12.341), (struct.pack(lines.Y.fmt, 107.301), 107.301), (struct.pack(lines.Pressure.fmt, 0.351), 0.351), (struct.pack(lines.RotX.fmt, 0.03), 0.03), (struct.pack(lines.RotY.fmt, 0.216), 0.216), ] for data in point_data_fragment: raw_bytes += data[0] # Set up the generator with the raw bytes: position = recover(raw_bytes) data = next(position) assert data == '' result = lines.Lines.load(position) assert result.count == 1 assert len(result.lines) == 1 result = result.lines[0] assert result.brush_type.name == 'pen' assert result.colour.name == 'black' assert result.line_attribute1.value == 0 assert result.brush_base_size.name == 'small' assert result.points.count == 1 result = result.points.points[0] assert round(result.x, 3) == 12.341 assert round(result.y, 3) == 107.301 assert round(result.pressure, 3) == 0.351 assert round(result.rot_x, 3) == 0.03 assert round(result.rot_y, 3) == 0.216
def test_recover_float(logger): """Verify the behaviour Float class used in parsing. """ raw_bytes = struct.pack('<f', 3.141) # Set up the generator with the raw bytes: position = recover(raw_bytes) data = next(position) assert data == '' assert round(Float.load(position).value, 3) == 3.141
def test_recover_int32(logger): """Verify the behaviour Int32 class used in parsing. """ raw_bytes = struct.pack('<I', 1001) # Set up the generator with the raw bytes: position = recover(raw_bytes) data = next(position) assert data == '' assert Int32.load(position).value == 1001
def test_line_attribute_brush_type(logger, raw_bytes, value, name): """Verify how lines.BrushBaseSize handles parsing. """ # Set up the generator with the raw bytes: position = recover(raw_bytes) data = next(position) assert data == '' result = lines.BrushType.load(position) assert result.value == value assert result.name == name
def test_file_header_parsing(logger): """ """ expected = 'reMarkable lines with selections and layers' raw_bytes = struct.pack('<43s', expected.encode('ascii')) position = recover(raw_bytes) next(position) file_header = FileHeader.load(position) assert file_header.header == expected
def test_line_attribute_lineattribute1(logger): """Verify how lines.LineAttribute1 handles parsing. """ raw_bytes = struct.pack(Int32.fmt, 0) # Set up the generator with the raw bytes: position = recover(raw_bytes) data = next(position) assert data == '' result = lines.LineAttribute1.load(position) assert result.value == 0
def test_primitives(logger, class_, raw_bytes, expected): """Verify basic conversion of the classes used by lines.Point """ # Set up the generator with the raw bytes: position = recover(raw_bytes) data = next(position) assert data == '' result = class_.load(position) if issubclass(class_, Float): assert round(result.value, 3) == expected else: assert result.value == expected
def test_recover_base(logger): """Verify the behaviour Int32 class used in parsing. """ class AnotherInt32(Base): fmt = '<I' def __init__(self, value): self.value = value raw_bytes = struct.pack(AnotherInt32.fmt, 9009) # Set up the generator with the raw bytes: position = recover(raw_bytes) data = next(position) assert data == '' assert AnotherInt32.load(position).value == 9009
def test_layers_dump_and_load(logger): """Test the dump and loading of layers-layer-empty lines instance. """ layer = Layer(Lines(0, [])) assert layer.lines.count == 0 layers = Layers(1, [layer]) assert layers.count == 1 assert len(layers.layers) == 1 assert layers.layers == [layer] raw_bytes = layers.dump() position = recover(raw_bytes) next(position) result = Layers.load(position) assert result.count == 1 assert len(result.layers) == 1 layer = result.layers[0] assert layer.lines.count == 0
def test_recover_generator(logger): """Verify the behaviour of the raw bytes parsing generator. """ class Char(object): fmt = 'c' raw_bytes = b'0123456789' # Set up the generator with the raw bytes: position = recover(raw_bytes) # Start the generator ready for reading in and converting bytes: data = next(position) assert data == '' # Parse out the characters for i in range(10): # recorver the next character data = position.send(Char) # verify it is correct: assert int(data) == i
def test_page_and_pages_dump_and_load(logger): """Test the dump and loading of pages-page-empty layers instance. """ page = Page(0, Layers(0, [])) assert page.number == 0 assert page.layers.count == 0 pages = Pages(1, [page]) assert pages.count == 1 assert len(pages.pages) == 1 assert pages.pages == [page] raw_bytes = pages.dump() position = recover(raw_bytes) next(position) result = Pages.load(position) assert result.count == 1 assert len(result.pages) == 1 page = result.pages[0] assert page.number == 0 assert page.layers.count == 0
def test_dump_Point(logger): """Test the dump and load of the Point structure. """ point = Point( x=12.341, y=107.301, pressure=0.351, rot_x=0.03, rot_y=0.216, ) raw_bytes = point.dump() position = recover(raw_bytes) next(position) result = Point.load(position) assert round(result.x, 3) == 12.341 assert round(result.y, 3) == 107.301 assert round(result.pressure, 3) == 0.351 assert round(result.rot_x, 3) == 0.03 assert round(result.rot_y, 3) == 0.216
def test_dump_Points_and_Point(logger): """Test the dump and load of the Points which contains Point instances. """ point = Point( x=12.341, y=107.301, pressure=0.351, rot_x=0.03, rot_y=0.216, ) points = Points(1, [point]) raw_bytes = points.dump() position = recover(raw_bytes) next(position) result = Points.load(position) assert result.count == 1 assert len(result.points) == 1 result = result.points[0] assert round(result.x, 3) == 12.341 assert round(result.y, 3) == 107.301 assert round(result.pressure, 3) == 0.351 assert round(result.rot_x, 3) == 0.03 assert round(result.rot_y, 3) == 0.216