예제 #1
0
def test_dict_json_v2():
    try:
        grid = hszinc.Grid(version=hszinc.VER_2_0)
        grid.column['comment'] = {}
        grid.column['value'] = {}
        grid.extend([{
            'comment': 'An empty dict',
            'value': {},
        }])
        hszinc.dump(grid, mode=hszinc.MODE_JSON)
        assert False, 'Project Haystack 2.0 doesn\'t support dict'
    except ValueError:
        pass
예제 #2
0
def test_list_zinc_v2():
    try:
        grid = hszinc.Grid(version=hszinc.VER_2_0)
        grid.column['comment'] = {}
        grid.column['value'] = {}
        grid.extend([{
            'comment': 'An empty list',
            'value': [],
        }])
        hszinc.dump(grid, mode=hszinc.MODE_ZINC)
        assert False, 'Project Haystack 2.0 doesn\'t support lists'
    except ValueError:
        pass
예제 #3
0
def _hzinc_response(data, **kwargs):
    if len(data.column) == 0:
        # trick to get an empty grid without crashing the dumper
        data.column['empty'] = {}
    return HttpResponse(hszinc.dump(data),
                        content_type="text/zinc;charset=utf-8",
                        **kwargs)
예제 #4
0
    def _post_grid(self, url, grid, headers=None, **kwargs):
        """
        Post a grid to the Haystack server.
        """

        if not self.isConnected:
            self.authenticate()

        if self._zinc:
            content_type = 'application/json'
            data = hszinc.dump(grid, mode=hszinc.MODE_JSON)
        else:
            content_type = 'text/zinc'
            data = hszinc.dump(grid, mode=hszinc.MODE_ZINC)

        return self._post_request(url, content_type, data, headers, **kwargs)
예제 #5
0
    def test_on_http_grid_response(self, server_session):
        (server, session) = server_session

        # Reset our counter
        session._on_http_grid_response_called = 0
        session._on_http_grid_response_last_args = None

        # Fetch a grid
        op = session._get_grid("dummy", callback=lambda *a, **kwa: None)

        # The operation should still be in progress
        assert not op.is_done

        # There shall be one request
        assert server.requests() == 1
        rq = server.next_request()
        # Make a grid to respond with
        expected = hszinc.Grid()

        expected.column["empty"] = {}
        rq.respond(
            status=200,
            headers={b"Content-Type": "text/zinc"},
            content=hszinc.dump(expected, mode=hszinc.MODE_ZINC),
        )

        # Our dummy function should have been called
        assert session._on_http_grid_response_called == 1
        assert isinstance(session._on_http_grid_response_last_args, tuple)
        assert len(session._on_http_grid_response_last_args) == 3

        (response, args, kwargs) = session._on_http_grid_response_last_args
        assert isinstance(response, HTTPResponse)
        assert len(args) == 0
        assert len(kwargs) == 0
예제 #6
0
    def __init__(self,
                 session,
                 uri,
                 grid,
                 args=None,
                 post_format=hszinc.MODE_ZINC,
                 **kwargs):
        """
        Initialise a POST request for the grid with the given grid,
        URI and arguments.

        :param session: Haystack HTTP session object.
        :param uri: Possibly partial URI relative to the server base address
                    to perform a query.  No arguments shall be given here.
        :param grid: Grid (or grids) to be posted to the server.
        :param post_format: What format to post grids in?
        :param args: Dictionary of key-value pairs to be given as arguments.
        """
        self._log = session._log.getChild("post_grid.%s" % uri)
        super(PostGridOperation, self).__init__(session=session,
                                                uri=uri,
                                                args=args,
                                                **kwargs)

        # Convert the grids to their native format
        self._body = hszinc.dump(grid, mode=post_format).encode("utf-8")
        if post_format == hszinc.MODE_ZINC:
            self._content_type = "text/zinc"
        else:
            self._content_type = "application/json"
    def _post_grid(self, url, grid, headers=None, **kwargs):
        """
        Post a grid to the Haystack server.
        """

        if not self.isConnected:
            self.authenticate()

        if self._zinc:
            content_type = 'application/json'
            data = hszinc.dump(grid, mode=hszinc.MODE_JSON)
        else:
            content_type = 'text/zinc'
            data = hszinc.dump(grid, mode=hszinc.MODE_ZINC)

        return self._post_request(url, content_type, data, headers, **kwargs)
예제 #8
0
def formats_view(request):
    g = hszinc.Grid()
    g.column['mime'] = {}
    g.column['read'] = {}
    g.column['write'] = {}
    g.extend([{
        'mime': 'text/zinc',
        'read': hszinc.MARKER,
        'write': hszinc.MARKER
    }])
    return HttpResponse(hszinc.dump(g), content_type="text/zinc;charset=utf-8")
예제 #9
0
    def test_formats(self, server_session):
        (server, session) = server_session
        op = session.formats()

        # The operation should still be in progress
        assert not op.is_done

        # There shall be one request
        assert server.requests() == 1
        rq = server.next_request()

        # Request shall be a GET
        assert rq.method == "GET", "Expecting GET, got %s" % rq

        # Request shall be for base + 'api/formats'
        assert rq.uri == BASE_URI + "api/formats"

        # Accept header shall be given
        assert rq.headers[b"Accept"] == "text/zinc"

        # Make a grid to respond with
        expected = hszinc.Grid()

        expected.column["mime"] = {}
        expected.column["receive"] = {}
        expected.column["send"] = {}
        expected.extend([
            {
                "mime": "text/csv",
                "receive": hszinc.MARKER,
                "send": hszinc.MARKER
            },
            {
                "mime": "text/zinc",
                "receive": hszinc.MARKER,
                "send": hszinc.MARKER
            },
            {
                "mime": "application/json",
                "receive": hszinc.MARKER,
                "send": hszinc.MARKER,
            },
        ])

        rq.respond(
            status=200,
            headers={b"Content-Type": "text/zinc"},
            content=hszinc.dump(expected, mode=hszinc.MODE_ZINC),
        )

        # State machine should now be done
        assert op.is_done
        actual = op.result
        grid_cmp(expected, actual)
예제 #10
0
    def test_about(self, server_session):
        (server, session) = server_session
        op = session.about()

        # The operation should still be in progress
        assert not op.is_done

        # There shall be one request
        assert server.requests() == 1
        rq = server.next_request()

        # Request shall be a GET
        assert rq.method == 'GET', 'Expecting GET, got %s' % rq

        # Request shall be for base + 'api/about'
        assert rq.uri == BASE_URI + 'api/about'

        # Accept header shall be given
        assert rq.headers[b'Accept'] == 'text/zinc'

        # Make a grid to respond with
        expected = hszinc.Grid()

        expected.column['haystackVersion'] = {}
        expected.column['tz'] = {}
        expected.column['serverName'] = {}
        expected.column['serverTime'] = {}
        expected.column['serverBootTime'] = {}
        expected.column['productName'] = {}
        expected.column['productUri'] = {}
        expected.column['productVersion'] = {}
        expected.column['moduleName'] = {}
        expected.column['moduleVersion'] = {}
        expected.append({
            'haystackVersion': '2.0',
            'tz': 'UTC',
            'serverName': 'pyhaystack dummy server',
            'serverTime': datetime.datetime.now(tz=pytz.UTC),
            'serverBootTime': datetime.datetime.now(tz=pytz.UTC),
            'productName': 'pyhaystack dummy server',
            'productVersion': '0.0.1',
            'productUri': hszinc.Uri('http://pyhaystack.readthedocs.io'),
            'moduleName': 'tests.client.base',
            'moduleVersion': '0.0.1',
        })

        rq.respond(status=200, headers={
            b'Content-Type': 'text/zinc',
        }, content=hszinc.dump(expected, mode=hszinc.MODE_ZINC))

        # State machine should now be done
        assert op.is_done
        actual = op.result
        grid_cmp(expected, actual)
예제 #11
0
    def test_about(self, server_session):
        (server, session) = server_session
        op = session.about()

        # The operation should still be in progress
        assert not op.is_done

        # There shall be one request
        assert server.requests() == 1
        rq = server.next_request()

        # Request shall be a GET
        assert rq.method == 'GET', 'Expecting GET, got %s' % rq

        # Request shall be for base + 'api/about'
        assert rq.uri == BASE_URI + 'api/about'

        # Accept header shall be given
        assert rq.headers['Accept'] == 'text/zinc'

        # Make a grid to respond with
        expected = hszinc.Grid()

        expected.column['haystackVersion'] = {}
        expected.column['tz'] = {}
        expected.column['serverName'] = {}
        expected.column['serverTime'] = {}
        expected.column['serverBootTime'] = {}
        expected.column['productName'] = {}
        expected.column['productUri'] = {}
        expected.column['productVersion'] = {}
        expected.column['moduleName'] = {}
        expected.column['moduleVersion'] = {}
        expected.append({
            'haystackVersion': '2.0',
            'tz': 'UTC',
            'serverName': 'pyhaystack dummy server',
            'serverTime': datetime.datetime.now(tz=pytz.UTC),
            'serverBootTime': datetime.datetime.now(tz=pytz.UTC),
            'productName': 'pyhaystack dummy server',
            'productVersion': '0.0.1',
            'productUri': hszinc.Uri('http://pyhaystack.readthedocs.io'),
            'moduleName': 'tests.client.base',
            'moduleVersion': '0.0.1',
        })

        rq.respond(status=200, headers={
            'Content-Type': 'text/zinc',
        }, content=hszinc.dump(expected, mode=hszinc.MODE_ZINC))

        # State machine should now be done
        assert op.is_done
        actual = op.result
        grid_cmp(expected, actual)
예제 #12
0
def test_data_types_v3():
    grid = hszinc.Grid(version=hszinc.VER_3_0)
    grid.column['comment'] = {}
    grid.column['value'] = {}
    grid.extend([
        {
            'comment': 'A NA',
            'value': hszinc.NA,
        },
        {
            'comment': 'An empty list',
            'value': [],
        },
        {
            'comment': 'A null value in a list',
            'value': [None],
        },
        {
            'comment': 'A marker in a list',
            'value': [hszinc.MARKER],
        },
        {
            'comment': 'Booleans',
            'value': [True, False],
        },
        {
            'comment': 'References',
            'value': [hszinc.Ref('a-ref'),
                      hszinc.Ref('a-ref', 'a value')],
        },
        {
            'comment': 'A quantity',
            'value': [hszinc.Quantity(500, 'miles')],
        },
        {
            'comment': 'A XStr',
            'value': [hszinc.XStr("hex", 'deadbeef')],
        },
    ])
    grid_str = hszinc.dump(grid)
    ref_str = '''ver:"3.0"
comment,value
"A NA",NA
"An empty list",[]
"A null value in a list",[N]
"A marker in a list",[M]
"Booleans",[T,F]
"References",[@a-ref,@a-ref "a value"]
"A quantity",[500miles]
"A XStr",[hex("deadbeef")]
'''
    assert grid_str == ref_str
예제 #13
0
    def test_get_single_entity(self, server_session):
        (server, session) = server_session
        # Try retrieving an existing single entity
        op = session.get_entity("my.entity.id", single=True)

        # The operation should still be in progress
        assert not op.is_done

        # There shall be one request
        assert server.requests() == 1
        rq = server.next_request()

        # Request shall be a GET
        assert rq.method == "GET", "Expecting GET, got %s" % rq

        # Request shall be for base + 'api/[email protected]'
        assert rq.uri == BASE_URI + "api/read?id=%40my.entity.id"

        # Accept header shall be given
        assert rq.headers[b"Accept"] == "text/zinc"

        # Make a grid to respond with
        response = hszinc.Grid()

        response.column["id"] = {}
        response.column["dis"] = {}
        response.column["randomTag"] = {}
        response.append({
            "id": hszinc.Ref("my.entity.id", value="id"),
            "dis": "A test entity",
            "randomTag": hszinc.MARKER,
        })

        rq.respond(
            status=200,
            headers={b"Content-Type": "text/zinc"},
            content=hszinc.dump(response, mode=hszinc.MODE_ZINC),
        )

        # State machine should now be done
        assert op.is_done
        entity = op.result
        # Response should be an entity
        assert isinstance(entity, Entity), "%r not an entity" % entity
        # The tags should be passed through from the response
        assert entity.id.name == "my.entity.id"
        assert entity.tags["dis"] == response[0]["dis"]
        assert entity.tags["randomTag"] == response[0]["randomTag"]
예제 #14
0
    def test_formats(self, server_session):
        (server, session) = server_session
        op = session.formats()

        # The operation should still be in progress
        assert not op.is_done

        # There shall be one request
        assert server.requests() == 1
        rq = server.next_request()

        # Request shall be a GET
        assert rq.method == 'GET', 'Expecting GET, got %s' % rq

        # Request shall be for base + 'api/formats'
        assert rq.uri == BASE_URI + 'api/formats'

        # Accept header shall be given
        assert rq.headers[b'Accept'] == 'text/zinc'

        # Make a grid to respond with
        expected = hszinc.Grid()

        expected.column['mime'] = {}
        expected.column['receive'] = {}
        expected.column['send'] = {}
        expected.extend([{
                "mime": "text/csv",
                "receive": hszinc.MARKER,
                "send": hszinc.MARKER,
            }, {
                "mime": "text/zinc",
                "receive": hszinc.MARKER,
                "send": hszinc.MARKER,
            }, {
                "mime": "application/json",
                "receive": hszinc.MARKER,
                "send": hszinc.MARKER,
        }])

        rq.respond(status=200, headers={
            b'Content-Type': 'text/zinc',
        }, content=hszinc.dump(expected, mode=hszinc.MODE_ZINC))

        # State machine should now be done
        assert op.is_done
        actual = op.result
        grid_cmp(expected, actual)
    def test_get_single_entity(self, server_session):
        (server, session) = server_session
        # Try retrieving an existing single entity
        op = session.get_entity('my.entity.id', single=True)

        # The operation should still be in progress
        assert not op.is_done

        # There shall be one request
        assert server.requests() == 1
        rq = server.next_request()

        # Request shall be a GET
        assert rq.method == 'GET', 'Expecting GET, got %s' % rq

        # Request shall be for base + 'api/[email protected]'
        assert rq.uri == BASE_URI + 'api/read?id=%40my.entity.id'

        # Accept header shall be given
        assert rq.headers[b'Accept'] == 'text/zinc'

        # Make a grid to respond with
        response = hszinc.Grid()

        response.column['id'] = {}
        response.column['dis'] = {}
        response.column['randomTag'] = {}
        response.append({
            'id': hszinc.Ref('my.entity.id', value='id'),
            'dis': 'A test entity',
            'randomTag': hszinc.MARKER
        })

        rq.respond(status=200,
                   headers={
                       b'Content-Type': 'text/zinc',
                   },
                   content=hszinc.dump(response, mode=hszinc.MODE_ZINC))

        # State machine should now be done
        assert op.is_done
        entity = op.result
        # Response should be an entity
        assert isinstance(entity, Entity), '%r not an entity' % entity
        # The tags should be passed through from the response
        assert entity.id.name == 'my.entity.id'
        assert entity.tags['dis'] == response[0]['dis']
        assert entity.tags['randomTag'] == response[0]['randomTag']
예제 #16
0
def test_grid_types_json():
    innergrid = hszinc.Grid(version=hszinc.VER_3_0)
    innergrid.column['comment'] = {}
    innergrid.extend([
        {
            'comment': 'A innergrid',
        },
    ])
    grid = hszinc.Grid(version=hszinc.VER_3_0)
    grid.column['inner'] = {}
    grid.extend([
        {
            'inner': innergrid,
        },
    ])
    grid_str = hszinc.dump(grid, mode=hszinc.MODE_JSON)
    grid_json = json.loads(grid_str)
    assert grid_json == {
        'meta': {
            'ver': '3.0'
        },
        'cols': [
            {
                'name': 'inner'
            },
        ],
        'rows': [
            {
                'inner': {
                    'meta': {
                        'ver': '3.0'
                    },
                    'cols': [
                        {
                            'name': 'comment'
                        },
                    ],
                    'rows': [
                        {
                            'comment': 's:A innergrid'
                        },
                    ],
                }
            },
        ],
    }
예제 #17
0
    def test_get_single_entity(self, server_session):
        (server, session) = server_session
        # Try retrieving an existing single entity
        op = session.get_entity('my.entity.id', single=True)

        # The operation should still be in progress
        assert not op.is_done

        # There shall be one request
        assert server.requests() == 1
        rq = server.next_request()

        # Request shall be a GET
        assert rq.method == 'GET', 'Expecting GET, got %s' % rq

        # Request shall be for base + 'api/[email protected]'
        assert rq.uri == BASE_URI + 'api/read?id=%40my.entity.id'

        # Accept header shall be given
        assert rq.headers[b'Accept'] == 'text/zinc'

        # Make a grid to respond with
        response = hszinc.Grid()

        response.column['id'] = {}
        response.column['dis'] = {}
        response.column['randomTag'] = {}
        response.append({
            'id': hszinc.Ref('my.entity.id', value='id'),
            'dis': 'A test entity',
            'randomTag': hszinc.MARKER
        })

        rq.respond(status=200, headers={
            b'Content-Type': 'text/zinc',
        }, content=hszinc.dump(response, mode=hszinc.MODE_ZINC))

        # State machine should now be done
        assert op.is_done
        entity = op.result
        # Response should be an entity
        assert isinstance(entity, Entity), '%r not an entity' % entity
        # The tags should be passed through from the response
        assert entity.id.name == 'my.entity.id'
        assert entity.tags['dis'] == response[0]['dis']
        assert entity.tags['randomTag'] == response[0]['randomTag']
예제 #18
0
def test_grid_meta_json():
    grid_json = json.loads(hszinc.dump(make_grid_meta(),
        mode=hszinc.MODE_JSON))
    assert grid_json == {
            'meta': {
                'ver': '2.0',
                'aString': 's:aValue',
                'aNumber': 'n:3.141590',
                'aNull': None,
                'aMarker': 'm:',
                'aQuantity': 'n:123.000000 Hz',
            },
            'cols': [
                {'name': 'empty'},
            ],
            'rows': [],
    }
예제 #19
0
def test_grid_meta_json():
    grid_json = json.loads(hszinc.dump(make_grid_meta(),
        mode=hszinc.MODE_JSON))
    assert grid_json == {
            'meta': {
                'ver': '2.0',
                'aString': 's:aValue',
                'aNumber': 'n:3.141590',
                'aNull': None,
                'aMarker': 'm:',
                'aQuantity': 'n:123.000000 Hz',
            },
            'cols': [
                {'name': 'empty'},
            ],
            'rows': [],
    }
예제 #20
0
    def test_get_single_entity_missing(self, server_session):
        (server, session) = server_session
        # Try retrieving an existing single entity that does not exist
        op = session.get_entity("my.nonexistent.id", single=True)

        # The operation should still be in progress
        assert not op.is_done

        # There shall be one request
        assert server.requests() == 1
        rq = server.next_request()

        # Request shall be a GET
        assert rq.method == "GET", "Expecting GET, got %s" % rq

        # Request shall be for base + 'api/[email protected]'
        assert rq.uri == BASE_URI + "api/read?id=%40my.nonexistent.id"

        # Accept header shall be given
        assert rq.headers[b"Accept"] == "text/zinc"

        # Make a grid to respond with.  Note, server might also choose to
        # throw an error, but we'll pretend it doesn't.
        response = hszinc.Grid()

        response.column["id"] = {}
        response.column["dis"] = {}

        rq.respond(
            status=200,
            headers={b"Content-Type": "text/zinc"},
            content=hszinc.dump(response, mode=hszinc.MODE_ZINC),
        )

        # State machine should now be done
        assert op.is_done
        # This should trigger a name error:
        try:
            entity = op.result
            assert entity is None
        except NameError as e:
            assert str(e) == "No matching entity found"
예제 #21
0
def _try_dump_parse(ref_grid, mode):
    try:
        # Dump the randomised grid to a string
        grid_str = hszinc.dump(ref_grid, mode=mode)
    except:
        # Dump some detail about the grid
        print('Failed to dump grid.')
        dump_grid(ref_grid)
        raise

    # Parse the grid string
    try:
        parsed_grid = hszinc.parse(grid_str, mode=mode, single=True)
    except:
        print('Failed to parse dumped grid')
        dump_grid(ref_grid)
        print('--- Parsed string ---')
        print(grid_str)
        raise

    approx_check_grid(parsed_grid, ref_grid)
예제 #22
0
    def test_read_one_id(self, server_session):
        (server, session) = server_session
        op = session.read(hszinc.Ref('my.entity.id'))

        # The operation should still be in progress
        assert not op.is_done

        # There shall be one request
        assert server.requests() == 1
        rq = server.next_request()

        # Request shall be a GET
        assert rq.method == 'GET', 'Expecting GET, got %s' % rq

        # Request shall be for a specific URI
        assert rq.uri == BASE_URI + 'api/read?id=%40my.entity.id'

        # Accept header shall be given
        assert rq.headers[b'Accept'] == 'text/zinc'

        # Make a grid to respond with
        expected = hszinc.Grid()

        expected.column['id'] = {}
        expected.column['dis'] = {}
        expected.extend([{
            "id": hszinc.Ref('my.entity.id'),
            "dis": 'my entity'
        }])

        rq.respond(status=200,
                   headers={
                       b'Content-Type': 'text/zinc',
                   },
                   content=hszinc.dump(expected, mode=hszinc.MODE_ZINC))

        # State machine should now be done
        assert op.is_done
        actual = op.result
        grid_cmp(expected, actual)
예제 #23
0
    def test_get_single_entity_missing(self, server_session):
        (server, session) = server_session
        # Try retrieving an existing single entity that does not exist
        op = session.get_entity('my.nonexistent.id', single=True)

        # The operation should still be in progress
        assert not op.is_done

        # There shall be one request
        assert server.requests() == 1
        rq = server.next_request()

        # Request shall be a GET
        assert rq.method == 'GET', 'Expecting GET, got %s' % rq

        # Request shall be for base + 'api/[email protected]'
        assert rq.uri == BASE_URI + 'api/read?id=%40my.nonexistent.id'

        # Accept header shall be given
        assert rq.headers[b'Accept'] == 'text/zinc'

        # Make a grid to respond with.  Note, server might also choose to
        # throw an error, but we'll pretend it doesn't.
        response = hszinc.Grid()

        response.column['id'] = {}
        response.column['dis'] = {}

        rq.respond(status=200, headers={
            b'Content-Type': 'text/zinc',
        }, content=hszinc.dump(response, mode=hszinc.MODE_ZINC))

        # State machine should now be done
        assert op.is_done
        # This should trigger a name error:
        try:
            entity = op.result
            assert entity is None
        except NameError as e:
            assert str(e) == 'No matching entity found'
예제 #24
0
    def test_read_one_id(self, server_session):
        (server, session) = server_session
        op = session.read(hszinc.Ref("my.entity.id"))

        # The operation should still be in progress
        assert not op.is_done

        # There shall be one request
        assert server.requests() == 1
        rq = server.next_request()

        # Request shall be a GET
        assert rq.method == "GET", "Expecting GET, got %s" % rq

        # Request shall be for a specific URI
        assert rq.uri == BASE_URI + "api/read?id=%40my.entity.id"

        # Accept header shall be given
        assert rq.headers[b"Accept"] == "text/zinc"

        # Make a grid to respond with
        expected = hszinc.Grid()

        expected.column["id"] = {}
        expected.column["dis"] = {}
        expected.extend([{
            "id": hszinc.Ref("my.entity.id"),
            "dis": "my entity"
        }])

        rq.respond(
            status=200,
            headers={b"Content-Type": "text/zinc"},
            content=hszinc.dump(expected, mode=hszinc.MODE_ZINC),
        )

        # State machine should now be done
        assert op.is_done
        actual = op.result
        grid_cmp(expected, actual)
예제 #25
0
def test_scalar_dict_zinc_v3():
    grid = hszinc.Grid(version=hszinc.VER_3_0)
    grid.column['comment'] = {}
    grid.column['value'] = {}
    grid.extend([
        {
            'comment': 'An empty dict',
            'value': {},
        },
        {
            'comment': 'A marker in a dict',
            'value': {
                "marker": hszinc.MARKER
            },
        },
        {
            'comment': 'A references in a dict',
            'value': {
                "ref": hszinc.Ref('a-ref'),
                "ref2": hszinc.Ref('a-ref', 'a value')
            },
        },
        {
            'comment': 'A quantity in a dict',
            'value': {
                "quantity": hszinc.Quantity(500, 'miles')
            },
        },
    ])
    grid_str = hszinc.dump(grid, mode=hszinc.MODE_ZINC)
    assert grid_str == ("ver:\"3.0\"\n"
                        "comment,value\n"
                        "\"An empty dict\",{}\n"
                        "\"A marker in a dict\",{marker:M}\n"
                        "\"A references in a dict\",{" +
                        " ".join([str(k) + ":" + str(v) for k, v in {"ref": "@a-ref", "ref2": "@a-ref"}.items()]) \
                        .replace("ref2:@a-ref", "ref2:@a-ref \"a value\"") + \
                        "}\n"
                        "\"A quantity in a dict\",{quantity:500miles}\n")
예제 #26
0
def test_grid_types_zinc():
    innergrid = hszinc.Grid(version=hszinc.VER_3_0)
    innergrid.column['comment'] = {}
    innergrid.extend([
        {
            'comment': 'A innergrid',
        },
    ])
    grid = hszinc.Grid(version=hszinc.VER_3_0)
    grid.column['inner'] = {}
    grid.extend([
        {
            'inner': innergrid,
        },
    ])
    grid_str = hszinc.dump(grid, mode=hszinc.MODE_ZINC)
    assert grid_str == ('ver:"3.0"\n'
                        'inner\n'
                        '<<ver:"3.0"\n'
                        'comment\n'
                        '"A innergrid"\n'
                        '>>\n')
예제 #27
0
    def test_read_one_id(self, server_session):
        (server, session) = server_session
        op = session.read(hszinc.Ref('my.entity.id'))

        # The operation should still be in progress
        assert not op.is_done

        # There shall be one request
        assert server.requests() == 1
        rq = server.next_request()

        # Request shall be a GET
        assert rq.method == 'GET', 'Expecting GET, got %s' % rq

        # Request shall be for a specific URI
        assert rq.uri == BASE_URI + 'api/read?id=%40my.entity.id'

        # Accept header shall be given
        assert rq.headers[b'Accept'] == 'text/zinc'

        # Make a grid to respond with
        expected = hszinc.Grid()

        expected.column['id'] = {}
        expected.column['dis'] = {}
        expected.extend([{
                "id": hszinc.Ref('my.entity.id'),
                "dis": 'my entity'
        }])

        rq.respond(status=200, headers={
            b'Content-Type': 'text/zinc',
        }, content=hszinc.dump(expected, mode=hszinc.MODE_ZINC))

        # State machine should now be done
        assert op.is_done
        actual = op.result
        grid_cmp(expected, actual)
예제 #28
0
    def __init__(self, session, uri, grid, args=None,
            post_format=hszinc.MODE_ZINC, **kwargs):
        """
        Initialise a POST request for the grid with the given grid,
        URI and arguments.

        :param session: Haystack HTTP session object.
        :param uri: Possibly partial URI relative to the server base address
                    to perform a query.  No arguments shall be given here.
        :param grid: Grid (or grids) to be posted to the server.
        :param post_format: What format to post grids in?
        :param args: Dictionary of key-value pairs to be given as arguments.
        """
        self._log = session._log.getChild('post_grid.%s' % uri)
        super(PostGridOperation, self).__init__(
                session=session, uri=uri, args=args, **kwargs)

        # Convert the grids to their native format
        self._body = hszinc.dump(grid, mode=post_format).encode('utf-8')
        if post_format == hszinc.MODE_ZINC:
            self._content_type = 'text/zinc'
        else:
            self._content_type = 'application/json'
예제 #29
0
    def test_read_many_id(self, server_session):
        (server, session) = server_session
        op = session.read([
            hszinc.Ref('my.entity.id1'),
            hszinc.Ref('my.entity.id2'),
            hszinc.Ref('my.entity.id3'),
        ])

        # The operation should still be in progress
        assert not op.is_done

        # There shall be one request
        assert server.requests() == 1
        rq = server.next_request()

        # Request shall be a GET
        assert rq.method == 'POST', 'Expecting POST, got %s' % rq

        # Request shall be for a specific URI
        assert rq.uri == BASE_URI + 'api/read'

        # Body shall be in ZINC
        assert rq.headers['Content-Type'] == 'text/zinc'

        # Body shall be a single valid grid of this form:
        expected = hszinc.Grid()
        expected.column['id'] = {}
        expected.extend([{
                "id": hszinc.Ref('my.entity.id1'),
            }, {
                "id": hszinc.Ref('my.entity.id2'),
            }, {
                "id": hszinc.Ref('my.entity.id3'),
        }])
        actual = hszinc.parse(rq.body, mode=hszinc.MODE_ZINC)
        assert len(actual) == 1
        grid_cmp(expected, actual[0])

        # Accept header shall be given
        assert rq.headers['Accept'] == 'text/zinc'

        # Make a grid to respond with
        expected = hszinc.Grid()

        expected.column['id'] = {}
        expected.column['dis'] = {}
        expected.extend([{
                "id": hszinc.Ref('my.entity.id1'),
                "dis": 'my entity 1'
            }, {
                "id": hszinc.Ref('my.entity.id2'),
                "dis": 'my entity 2'
            }, {
                "id": hszinc.Ref('my.entity.id3'),
                "dis": 'my entity 3'
        }])

        rq.respond(status=200, headers={
            'Content-Type': 'text/zinc',
        }, content=hszinc.dump(expected, mode=hszinc.MODE_ZINC))

        # State machine should now be done
        assert op.is_done
        actual = op.result
        grid_cmp(expected, actual)
예제 #30
0
    def test_ops(self, server_session):
        (server, session) = server_session
        op = session.ops()

        # The operation should still be in progress
        assert not op.is_done

        # There shall be one request
        assert server.requests() == 1
        rq = server.next_request()

        # Request shall be a GET
        assert rq.method == 'GET', 'Expecting GET, got %s' % rq

        # Request shall be for base + 'api/ops'
        assert rq.uri == BASE_URI + 'api/ops'

        # Accept header shall be given
        assert rq.headers[b'Accept'] == 'text/zinc'

        # Make a grid to respond with
        expected = hszinc.Grid()

        expected.column['name'] = {}
        expected.column['summary'] = {}
        expected.extend([{
                "name": "about",
                "summary": "Summary information for server"
            }, {
                "name": "ops",
                "summary": "Operations supported by this server"
            }, {
                "name": "formats",
                "summary": "Grid data formats supported by this server"
            }, {
                "name": "read",
                "summary": "Read records by id or filter"
            }, {
                "name": "hisRead",
                "summary": "Read historical records"
            }, {
                "name": "hisWrite",
                "summary": "Write historical records"
            }, {
                "name": "nav",
                "summary": "Navigate a project"
            }, {
                "name": "watchSub",
                "summary": "Subscribe to change notifications"
            }, {
                "name": "watchUnsub",
                "summary": "Unsubscribe from change notifications"
            }, {
                "name": "watchPoll",
                "summary": "Poll for changes in watched points"
            }, {
                "name": "pointWrite",
                "summary": "Write a real-time value to a point"
            }, {
                "name": "invokeAction",
                "summary": "Invoke an action on an entity"
        }])

        rq.respond(status=200, headers={
            b'Content-Type': 'text/zinc',
        }, content=hszinc.dump(expected, mode=hszinc.MODE_ZINC))

        # State machine should now be done
        assert op.is_done
        actual = op.result
        grid_cmp(expected, actual)
예제 #31
0
def test_multi_grid_json():
    grids = [make_simple_grid(), make_metadata_grid()]
    grid_json = json.loads(hszinc.dump(grids, mode=hszinc.MODE_JSON))

    assert grid_json[0] == SIMPLE_EXAMPLE_JSON
    assert grid_json[1] == METADATA_EXAMPLE_JSON
예제 #32
0
def test_metadata_json():
    grid = make_metadata_grid()
    grid_json = json.loads(hszinc.dump(grid, mode=hszinc.MODE_JSON))
    assert grid_json == METADATA_EXAMPLE_JSON
예제 #33
0
    def test_read_many_id(self, server_session):
        (server, session) = server_session
        op = session.read([
            hszinc.Ref("my.entity.id1"),
            hszinc.Ref("my.entity.id2"),
            hszinc.Ref("my.entity.id3"),
        ])

        # The operation should still be in progress
        assert not op.is_done

        # There shall be one request
        assert server.requests() == 1
        rq = server.next_request()

        # Request shall be a GET
        assert rq.method == "POST", "Expecting POST, got %s" % rq

        # Request shall be for a specific URI
        assert rq.uri == BASE_URI + "api/read"

        # Body shall be in ZINC
        assert rq.headers[b"Content-Type"] == "text/zinc"

        # Body shall be a single valid grid of this form:
        expected = hszinc.Grid()
        expected.column["id"] = {}
        expected.extend([
            {
                "id": hszinc.Ref("my.entity.id1")
            },
            {
                "id": hszinc.Ref("my.entity.id2")
            },
            {
                "id": hszinc.Ref("my.entity.id3")
            },
        ])
        actual = hszinc.parse(rq.body.decode("utf-8"), mode=hszinc.MODE_ZINC)
        assert len(actual) == 1
        grid_cmp(expected, actual[0])

        # Accept header shall be given
        assert rq.headers[b"Accept"] == "text/zinc"

        # Make a grid to respond with
        expected = hszinc.Grid()

        expected.column["id"] = {}
        expected.column["dis"] = {}
        expected.extend([
            {
                "id": hszinc.Ref("my.entity.id1"),
                "dis": "my entity 1"
            },
            {
                "id": hszinc.Ref("my.entity.id2"),
                "dis": "my entity 2"
            },
            {
                "id": hszinc.Ref("my.entity.id3"),
                "dis": "my entity 3"
            },
        ])

        rq.respond(
            status=200,
            headers={b"Content-Type": "text/zinc"},
            content=hszinc.dump(expected, mode=hszinc.MODE_ZINC),
        )

        # State machine should now be done
        assert op.is_done
        actual = op.result
        grid_cmp(expected, actual)
예제 #34
0
def try_dump_parse():
    # Generate a randomised grid of values and try parsing it back.
    ref_grid = hszinc.Grid()
    ref_grid.metadata.extend(gen_random_meta())

    # Randomised columns
    for n in range(0, random.randint(1,5)):
        col_name = gen_random_name(existing=ref_grid.column)
        if random.choice([True,False]):
            ref_grid.column[col_name] = gen_random_meta()
        else:
            ref_grid.column[col_name] = {}

    # Randomised rows
    for n in range(0, random.randint(0,20)):
        row = {}
        for c in ref_grid.column.keys():
            if random.choice([True,False]):
                row[c] = gen_random_scalar()
        ref_grid.append(row)

    try:
        # Dump the randomised grid to a string
        grid_str = hszinc.dump(ref_grid)
    except:
        # Dump some detail about the grid
        print ('Failed to dump grid.')
        dump_grid(ref_grid)
        raise

    # Parse the grid string
    try:
        grid_list = hszinc.parse(grid_str)
    except:
        print ('Failed to parse dumped grid')
        dump_grid(ref_grid)
        print ('--- Parsed string ---')
        print (grid_str)
        raise

    assert len(grid_list) == 1
    parsed_grid = grid_list.pop(0)

    # Check metadata matches
    try:
        assert list(ref_grid.metadata.keys()) \
                == list(parsed_grid.metadata.keys())
        for key in ref_grid.metadata.keys():
            approx_check(ref_grid.metadata[key], parsed_grid.metadata[key])
    except:
        print ('Mismatch in metadata')
        print ('Reference grid')
        dump_grid(ref_grid)
        print ('Parsed grid')
        dump_grid(parsed_grid)
        raise

    try:
        # Check column matches
        assert list(ref_grid.column.keys()) \
                == list(parsed_grid.column.keys())
    except:
        print ('Mismatch in column')
        print ('Reference grid')
        dump_grid(ref_grid)
        print ('Parsed grid')
        dump_grid(parsed_grid)
        raise
    for col in ref_grid.column.keys():
        try:
            for key in ref_grid.column[col].keys():
                approx_check(ref_grid.column[col][key], \
                        parsed_grid.column[col][key])
        except:
            print ('Mismatch in metadata for column %s' % col)
            print ('Reference: %r' % ref_grid.column[col])
            print ('Parsed:    %r' % parsed_grid.column[col])
            raise

    try:
        # Check row matches
        assert len(ref_grid) == len(parsed_grid)
    except:
        print ('Mismatch in row count')
        print ('Reference grid')
        dump_grid(ref_grid)
        print ('Parsed grid')
        dump_grid(parsed_grid)

    for (ref_row, parsed_row) in zip(ref_grid, parsed_grid):
        try:
            for col in ref_grid.column.keys():
                approx_check(ref_row.get(col), parsed_row.get(col))
        except:
            print ('Mismatch in row')
            print ('Reference:')
            print (ref_row)
            print ('Parsed:')
            print (parsed_row)
            raise
예제 #35
0
    def test_about(self, server_session):
        (server, session) = server_session
        op = session.about()

        # The operation should still be in progress
        assert not op.is_done

        # There shall be one request
        assert server.requests() == 1
        rq = server.next_request()

        # Request shall be a GET
        assert rq.method == "GET", "Expecting GET, got %s" % rq

        # Request shall be for base + 'api/about'
        assert rq.uri == BASE_URI + "api/about"

        # Accept header shall be given
        assert rq.headers[b"Accept"] == "text/zinc"

        # Make a grid to respond with
        expected = hszinc.Grid()

        expected.column["haystackVersion"] = {}
        expected.column["tz"] = {}
        expected.column["serverName"] = {}
        expected.column["serverTime"] = {}
        expected.column["serverBootTime"] = {}
        expected.column["productName"] = {}
        expected.column["productUri"] = {}
        expected.column["productVersion"] = {}
        expected.column["moduleName"] = {}
        expected.column["moduleVersion"] = {}
        expected.append({
            "haystackVersion":
            "2.0",
            "tz":
            "UTC",
            "serverName":
            "pyhaystack dummy server",
            "serverTime":
            datetime.datetime.now(tz=pytz.UTC),
            "serverBootTime":
            datetime.datetime.now(tz=pytz.UTC),
            "productName":
            "pyhaystack dummy server",
            "productVersion":
            "0.0.1",
            "productUri":
            hszinc.Uri("http://pyhaystack.readthedocs.io"),
            "moduleName":
            "tests.client.base",
            "moduleVersion":
            "0.0.1",
        })

        rq.respond(
            status=200,
            headers={b"Content-Type": "text/zinc"},
            content=hszinc.dump(expected, mode=hszinc.MODE_ZINC),
        )

        # State machine should now be done
        assert op.is_done
        actual = op.result
        grid_cmp(expected, actual)
예제 #36
0
def test_multi_grid_json():
    grids = [make_simple_grid(), make_metadata_grid()]
    grid_json = json.loads(hszinc.dump(grids, mode=hszinc.MODE_JSON))

    assert grid_json[0] == SIMPLE_EXAMPLE_JSON
    assert grid_json[1] == METADATA_EXAMPLE_JSON
예제 #37
0
    def test_get_multi_entity(self, server_session):
        (server, session) = server_session
        # Try retrieving existing multiple entities
        op = session.get_entity(["my.entity.id1", "my.entity.id2"],
                                single=False)

        # The operation should still be in progress
        assert not op.is_done

        # There shall be one request
        assert server.requests() == 1
        rq = server.next_request()

        # Request shall be a POST
        assert rq.method == "POST", "Expecting POST, got %s" % rq

        # Request shall be for base + 'api/[email protected]'
        assert rq.uri == BASE_URI + "api/read"

        # Accept header shall be given
        assert rq.headers[b"Accept"] == "text/zinc"
        assert rq.headers[b"Content-Type"] == "text/zinc"

        # Body shall be a single grid:
        rq_grid = hszinc.parse(rq.body.decode("utf-8"),
                               mode=hszinc.MODE_ZINC,
                               single=True)

        # It shall have one column; id
        assert set(rq_grid.column.keys()) == set(["id"])
        # It shall have 2 rows
        assert len(rq_grid) == 2
        # Each row should only have 'id' values
        assert all([(set(r.keys()) == set(["id"])) for r in rq_grid])
        # The rows' 'id' column should *only* contain Refs.
        assert all([isinstance(r["id"], hszinc.Ref) for r in rq_grid])
        # Both IDs shall be listed, we don't about order
        assert set([r["id"].name for r in rq_grid
                    ]) == set(["my.entity.id1", "my.entity.id2"])

        # Make a grid to respond with
        response = hszinc.Grid()

        response.column["id"] = {}
        response.column["dis"] = {}
        response.column["randomTag"] = {}
        response.extend([
            {
                "id": hszinc.Ref("my.entity.id1", value="id1"),
                "dis": "A test entity #1",
                "randomTag": hszinc.MARKER,
            },
            {
                "id": hszinc.Ref("my.entity.id2", value="id2"),
                "dis": "A test entity #2",
                "randomTag": hszinc.MARKER,
            },
        ])

        rq.respond(
            status=200,
            headers={b"Content-Type": "text/zinc"},
            content=hszinc.dump(response, mode=hszinc.MODE_ZINC),
        )

        # State machine should now be done
        assert op.is_done
        entities = op.result

        # Response should be a dict
        assert isinstance(entities, dict), "%r not a dict" % entities
        # Response should have these keys
        assert set(entities.keys()) == set(["my.entity.id1", "my.entity.id2"])

        entity = entities.pop("my.entity.id1")
        assert isinstance(entity, Entity), "%r not an entity" % entity
        # The tags should be passed through from the response
        assert entity.id.name == "my.entity.id1"
        assert entity.tags["dis"] == response[0]["dis"]
        assert entity.tags["randomTag"] == response[0]["randomTag"]

        entity = entities.pop("my.entity.id2")
        assert isinstance(entity, Entity), "%r not an entity" % entity
        # The tags should be passed through from the response
        assert entity.id.name == "my.entity.id2"
        assert entity.tags["dis"] == response[1]["dis"]
        assert entity.tags["randomTag"] == response[1]["randomTag"]
예제 #38
0
def test_simple_json():
    grid = make_simple_grid()
    grid_json = json.loads(hszinc.dump(grid, mode=hszinc.MODE_JSON))
    assert grid_json == SIMPLE_EXAMPLE_JSON
예제 #39
0
def test_metadata():
    grid = make_metadata_grid()
    grid_str = hszinc.dump(grid)
    assert grid_str == METADATA_EXAMPLE
예제 #40
0
def test_multi_grid():
    grids = [make_simple_grid(), make_metadata_grid()]
    grid_str = hszinc.dump(grids)

    assert grid_str == '\n'.join([SIMPLE_EXAMPLE, METADATA_EXAMPLE])
예제 #41
0
def test_multi_grid():
    grids = [make_simple_grid(), make_metadata_grid()]
    grid_str = hszinc.dump(grids)

    assert grid_str == '\n'.join([SIMPLE_EXAMPLE, METADATA_EXAMPLE])
예제 #42
0
def test_metadata_json():
    grid = make_metadata_grid()
    grid_json = json.loads(hszinc.dump(grid, mode=hszinc.MODE_JSON))
    assert grid_json == METADATA_EXAMPLE_JSON
예제 #43
0
def test_metadata():
    grid = make_metadata_grid()
    grid_str = hszinc.dump(grid)
    assert grid_str == METADATA_EXAMPLE
예제 #44
0
def test_col_meta():
    grid_str = hszinc.dump(make_col_meta())
    assert grid_str == '''ver:"2.0"
예제 #45
0
def test_simple_json():
    grid = make_simple_grid()
    grid_json = json.loads(hszinc.dump(grid, mode=hszinc.MODE_JSON))
    assert grid_json == SIMPLE_EXAMPLE_JSON
예제 #46
0
def test_data_types():
    grid = hszinc.Grid()
    grid.column['comment'] = {}
    grid.column['value'] = {}
    grid.extend([
        {
            'comment': 'A null value',
            'value': None,
        },
        {
            'comment': 'A marker',
            'value': hszinc.MARKER,
        },
        {
            'comment': 'A "remove" object',
            'value': hszinc.REMOVE,
        },
        {
            'comment': 'A boolean, indicating False',
            'value': False,
        },
        {
            'comment': 'A boolean, indicating True',
            'value': True,
        },
        {
            'comment': 'A reference, without value',
            'value': hszinc.Ref('a-ref'),
        },
        {
            'comment': 'A reference, with value',
            'value': hszinc.Ref('a-ref', 'a value'),
        },
        {
            'comment': 'A binary blob',
            'value': hszinc.Bin('text/plain'),
        },
        {
            'comment': 'A quantity',
            'value': hszinc.Quantity(500,'miles'),
        },
        {
            'comment': 'A quantity without unit',
            'value': hszinc.Quantity(500,None),
        },
        {
            'comment': 'A coordinate',
            'value': hszinc.Coordinate(-27.4725,153.003),
        },
        {
            'comment': 'A URI',
            'value': hszinc.Uri(u'http://www.example.com#`unicode:\u1234\u5678`'),
        },
        {
            'comment': 'A string',
            'value':    u'This is a test\n'\
                        u'Line two of test\n'\
                        u'\tIndented with "quotes", \\backslashes\\ and '\
                        u'Unicode characters: \u1234\u5678 and a $ dollar sign',
        },
        {
            'comment': 'A date',
            'value': datetime.date(2016,1,13),
        },
        {
            'comment': 'A time',
            'value': datetime.time(7,51,43,microsecond=12345),
        },
        {
            'comment': 'A timestamp (non-UTC)',
            'value': pytz.timezone('Europe/Berlin').localize(\
                    datetime.datetime(2016,1,13,7,51,42,12345)),
        },
        {
            'comment': 'A timestamp (UTC)',
            'value': pytz.timezone('UTC').localize(\
                    datetime.datetime(2016,1,13,7,51,42,12345)),
        },
    ])
    grid_str = hszinc.dump(grid)
    ref_str = '''ver:"2.0"
comment,value
"A null value",N
"A marker",M
"A \\"remove\\" object",R
"A boolean, indicating False",F
"A boolean, indicating True",T
"A reference, without value",@a-ref
"A reference, with value",@a-ref "a value"
"A binary blob",Bin(text/plain)
"A quantity",500miles
"A quantity without unit",500
"A coordinate",C(-27.472500,153.003000)
"A URI",`http://www.example.com#\\`unicode:\\u1234\\u5678\\``
"A string","This is a test\\nLine two of test\\n\\tIndented with \\"quotes\\", \\\\backslashes\\\\ and Unicode characters: \\u1234\\u5678 and a \\$ dollar sign"
"A date",2016-01-13
"A time",07:51:43.012345
"A timestamp (non-UTC)",2016-01-13T07:51:42.012345+01:00 Berlin
"A timestamp (UTC)",2016-01-13T07:51:42.012345+00:00 UTC
'''
    assert grid_str == ref_str
예제 #47
0
    def test_read_many_id(self, server_session):
        (server, session) = server_session
        op = session.read([
            hszinc.Ref('my.entity.id1'),
            hszinc.Ref('my.entity.id2'),
            hszinc.Ref('my.entity.id3'),
        ])

        # The operation should still be in progress
        assert not op.is_done

        # There shall be one request
        assert server.requests() == 1
        rq = server.next_request()

        # Request shall be a GET
        assert rq.method == 'POST', 'Expecting POST, got %s' % rq

        # Request shall be for a specific URI
        assert rq.uri == BASE_URI + 'api/read'

        # Body shall be in ZINC
        assert rq.headers[b'Content-Type'] == 'text/zinc'

        # Body shall be a single valid grid of this form:
        expected = hszinc.Grid()
        expected.column['id'] = {}
        expected.extend([{
                "id": hszinc.Ref('my.entity.id1'),
            }, {
                "id": hszinc.Ref('my.entity.id2'),
            }, {
                "id": hszinc.Ref('my.entity.id3'),
        }])
        actual = hszinc.parse(rq.body.decode('utf-8'),
                mode=hszinc.MODE_ZINC)
        assert len(actual) == 1
        grid_cmp(expected, actual[0])

        # Accept header shall be given
        assert rq.headers[b'Accept'] == 'text/zinc'

        # Make a grid to respond with
        expected = hszinc.Grid()

        expected.column['id'] = {}
        expected.column['dis'] = {}
        expected.extend([{
                "id": hszinc.Ref('my.entity.id1'),
                "dis": 'my entity 1'
            }, {
                "id": hszinc.Ref('my.entity.id2'),
                "dis": 'my entity 2'
            }, {
                "id": hszinc.Ref('my.entity.id3'),
                "dis": 'my entity 3'
        }])

        rq.respond(status=200, headers={
            b'Content-Type': 'text/zinc',
        }, content=hszinc.dump(expected, mode=hszinc.MODE_ZINC))

        # State machine should now be done
        assert op.is_done
        actual = op.result
        grid_cmp(expected, actual)
예제 #48
0
def test_data_types_json():
    grid = hszinc.Grid()
    grid.column['comment'] = {}
    grid.column['value'] = {}
    grid.extend([
        {
            'comment': 'A null value',
            'value': None,
        },
        {
            'comment': 'A marker',
            'value': hszinc.MARKER,
        },
        {
            'comment': 'A boolean, indicating False',
            'value': False,
        },
        {
            'comment': 'A boolean, indicating True',
            'value': True,
        },
        {
            'comment': 'A reference, without value',
            'value': hszinc.Ref('a-ref'),
        },
        {
            'comment': 'A reference, with value',
            'value': hszinc.Ref('a-ref', 'a value'),
        },
        {
            'comment': 'A binary blob',
            'value': hszinc.Bin('text/plain'),
        },
        {
            'comment': 'A quantity',
            'value': hszinc.Quantity(500,'miles'),
        },
        {
            'comment': 'A quantity without unit',
            'value': hszinc.Quantity(500,None),
        },
        {
            'comment': 'A coordinate',
            'value': hszinc.Coordinate(-27.4725,153.003),
        },
        {
            'comment': 'A URI',
            'value': hszinc.Uri('http://www.example.com'),
        },
        {
            'comment': 'A string',
            'value':    'This is a test\n'\
                        'Line two of test\n'\
                        '\tIndented with "quotes" and \\backslashes\\',
        },
        {
            'comment': 'A date',
            'value': datetime.date(2016,1,13),
        },
        {
            'comment': 'A time',
            'value': datetime.time(7,51,43,microsecond=12345),
        },
        {
            'comment': 'A timestamp (non-UTC)',
            'value': pytz.timezone('Europe/Berlin').localize(\
                    datetime.datetime(2016,1,13,7,51,42,12345)),
        },
        {
            'comment': 'A timestamp (UTC)',
            'value': pytz.timezone('UTC').localize(\
                    datetime.datetime(2016,1,13,7,51,42,12345)),
        },
    ])
    grid_json = json.loads(hszinc.dump(grid, mode=hszinc.MODE_JSON))
    assert grid_json == {
            'meta': {'ver':'2.0'},
            'cols': [
                {'name':'comment'},
                {'name':'value'},
            ],
            'rows': [
                {   'comment': 's:A null value',
                    'value': None},
                {   'comment': 's:A marker',
                    'value': 'm:'},
                {   'comment': 's:A boolean, indicating False',
                    'value': False},
                {   'comment': 's:A boolean, indicating True',
                    'value': True},
                {   'comment': 's:A reference, without value',
                    'value': 'r:a-ref'},
                {   'comment': 's:A reference, with value',
                    'value': 'r:a-ref a value'},
                {   'comment': 's:A binary blob',
                    'value': 'b:text/plain'},
                {   'comment': 's:A quantity',
                    'value': 'n:500.000000 miles'},
                {   'comment': 's:A quantity without unit',
                    'value': 'n:500.000000'},
                {   'comment': 's:A coordinate',
                    'value': 'c:-27.472500,153.003000'},
                {   'comment': 's:A URI',
                    'value': 'u:http://www.example.com'},
                {   'comment': 's:A string',
                    'value': 's:This is a test\n'\
                            'Line two of test\n'\
                            '\tIndented with \"quotes\" '\
                            'and \\backslashes\\'},
                {   'comment': 's:A date',
                    'value': 'd:2016-01-13'},
                {   'comment': 's:A time',
                    'value': 'h:07:51:43.012345'},
                {   'comment': 's:A timestamp (non-UTC)',
                    'value': 't:2016-01-13T07:51:42.012345+01:00 Berlin'},
                {   'comment': 's:A timestamp (UTC)',
                    'value': 't:2016-01-13T07:51:42.012345+00:00 UTC'},
            ],
    }
예제 #49
0
    def test_ops(self, server_session):
        (server, session) = server_session
        op = session.ops()

        # The operation should still be in progress
        assert not op.is_done

        # There shall be one request
        assert server.requests() == 1
        rq = server.next_request()

        # Request shall be a GET
        assert rq.method == 'GET', 'Expecting GET, got %s' % rq

        # Request shall be for base + 'api/ops'
        assert rq.uri == BASE_URI + 'api/ops'

        # Accept header shall be given
        assert rq.headers['Accept'] == 'text/zinc'

        # Make a grid to respond with
        expected = hszinc.Grid()

        expected.column['name'] = {}
        expected.column['summary'] = {}
        expected.extend([{
                "name": "about",
                "summary": "Summary information for server"
            }, {
                "name": "ops",
                "summary": "Operations supported by this server"
            }, {
                "name": "formats",
                "summary": "Grid data formats supported by this server"
            }, {
                "name": "read",
                "summary": "Read records by id or filter"
            }, {
                "name": "hisRead",
                "summary": "Read historical records"
            }, {
                "name": "hisWrite",
                "summary": "Write historical records"
            }, {
                "name": "nav",
                "summary": "Navigate a project"
            }, {
                "name": "watchSub",
                "summary": "Subscribe to change notifications"
            }, {
                "name": "watchUnsub",
                "summary": "Unsubscribe from change notifications"
            }, {
                "name": "watchPoll",
                "summary": "Poll for changes in watched points"
            }, {
                "name": "pointWrite",
                "summary": "Write a real-time value to a point"
            }, {
                "name": "invokeAction",
                "summary": "Invoke an action on an entity"
        }])

        rq.respond(status=200, headers={
            'Content-Type': 'text/zinc',
        }, content=hszinc.dump(expected, mode=hszinc.MODE_ZINC))

        # State machine should now be done
        assert op.is_done
        actual = op.result
        grid_cmp(expected, actual)
예제 #50
0
def test_simple():
    grid = make_simple_grid()
    grid_str = hszinc.dump(grid)
    assert grid_str == SIMPLE_EXAMPLE
예제 #51
0
def test_grid_meta():
    grid_str = hszinc.dump(make_grid_meta())
    assert grid_str == '''ver:"2.0" aString:"aValue" aNumber:3.14159 aNull:N aMarker aQuantity:123Hz
예제 #52
0
    def test_get_multi_entity(self, server_session):
        (server, session) = server_session
        # Try retrieving existing multiple entities
        op = session.get_entity(['my.entity.id1', 'my.entity.id2'],
                single=False)

        # The operation should still be in progress
        assert not op.is_done

        # There shall be one request
        assert server.requests() == 1
        rq = server.next_request()

        # Request shall be a POST
        assert rq.method == 'POST', 'Expecting POST, got %s' % rq

        # Request shall be for base + 'api/[email protected]'
        assert rq.uri == BASE_URI + 'api/read'

        # Accept header shall be given
        assert rq.headers[b'Accept'] == 'text/zinc'
        assert rq.headers[b'Content-Type'] == 'text/zinc'

        # Body shall be a single grid:
        rq_grid = hszinc.parse(rq.body.decode('utf-8'), mode=hszinc.MODE_ZINC)
        assert len(rq_grid) == 1
        rq_grid = rq_grid[0]

        # It shall have one column; id
        assert set(rq_grid.column.keys()) == set(['id'])
        # It shall have 2 rows
        assert len(rq_grid) == 2
        # Each row should only have 'id' values
        assert all([(set(r.keys()) == set(['id'])) for r in rq_grid])
        # The rows' 'id' column should *only* contain Refs.
        assert all([isinstance(r['id'], hszinc.Ref) for r in rq_grid])
        # Both IDs shall be listed, we don't about order
        assert set([r['id'].name for r in rq_grid]) \
                == set(['my.entity.id1', 'my.entity.id2'])

        # Make a grid to respond with
        response = hszinc.Grid()

        response.column['id'] = {}
        response.column['dis'] = {}
        response.column['randomTag'] = {}
        response.extend([{
            'id': hszinc.Ref('my.entity.id1', value='id1'),
            'dis': 'A test entity #1',
            'randomTag': hszinc.MARKER
            },{
            'id': hszinc.Ref('my.entity.id2', value='id2'),
            'dis': 'A test entity #2',
            'randomTag': hszinc.MARKER
            }])

        rq.respond(status=200, headers={
            b'Content-Type': 'text/zinc',
        }, content=hszinc.dump(response, mode=hszinc.MODE_ZINC))

        # State machine should now be done
        assert op.is_done
        entities = op.result
        # Response should be a dict
        assert isinstance(entities, dict), '%r not a dict' % entity
        # Response should have these keys
        assert set(entities.keys()) == set(['my.entity.id1','my.entity.id2'])

        entity = entities.pop('my.entity.id1')
        assert isinstance(entity, Entity), '%r not an entity' % entity
        # The tags should be passed through from the response
        assert entity.id.name == 'my.entity.id1'
        assert entity.tags['dis'] == response[0]['dis']
        assert entity.tags['randomTag'] == response[0]['randomTag']

        entity = entities.pop('my.entity.id2')
        assert isinstance(entity, Entity), '%r not an entity' % entity
        # The tags should be passed through from the response
        assert entity.id.name == 'my.entity.id2'
        assert entity.tags['dis'] == response[1]['dis']
        assert entity.tags['randomTag'] == response[1]['randomTag']