Exemple #1
0
def test_urilist_to_uri():
    uri = URI('/api/v1/')

    id_list = [
        '/api/v1/ns/model:sdf:', '/api/v1/ns/model:234:',
        '/api/v1/ns/model:rfv:'
    ]
    assert uri.uriListToMultiURI(id_list) == '/api/v1/ns/model:sdf:234:rfv:'

    id_list = [
        '/api/v1/ns/model:sdf:', '/api/v1/ns/model:234:www:',
        '/api/v1/ns/model:rfv:'
    ]
    assert uri.uriListToMultiURI(
        id_list) == '/api/v1/ns/model:sdf:234:www:rfv:'

    id_list = ['/api/v1/ns/model:234:www:']
    assert uri.uriListToMultiURI(id_list) == '/api/v1/ns/model:234:www:'

    id_list = [
        '/api/v1/ns/model:sdf:', '/api/v1/ns/model:234:www',
        '/api/v1/ns/model:rfv:'
    ]
    with pytest.raises(ValueError):
        uri.uriListToMultiURI(id_list)

    id_list = ['/api/v1/ns/model']
    uri.uriListToMultiURI(id_list) == []

    id_list = [
        '/api/v1/ns/model:sdf:', '/api/v1/ns/model', '/api/v1/ns/model:rfv:'
    ]
    uri.uriListToMultiURI(id_list) == '/api/v1/ns/model:sdf:rfv:'

    assert uri.uriListToMultiURI([]) == []
Exemple #2
0
def test_extract_ids():
  uri = URI( '/api/v1/' )

  id_list = [ '/api/v1/ns/model:sdf:', '/api/v1/ns/model:234:', '/api/v1/ns/model:rfv:' ]
  assert uri.extractIds( id_list ) == [ 'sdf', '234', 'rfv' ]

  id_list = [ '/api/v1/ns/model:sdf:', '/api/v1/ns/model:234:www:', '/api/v1/ns/model:rfv:' ]
  assert uri.extractIds( id_list ) == [ 'sdf', '234', 'www', 'rfv' ]

  id_list = [ '/api/v1/ns/model:234:www:' ]
  assert uri.extractIds( id_list ) == [ '234', 'www' ]

  id_list = [ '/api/v1/ns/model:sdf:', '/api/v1/ns/model:234:www', '/api/v1/ns/model:rfv:' ]
  with pytest.raises( ValueError ):
    uri.extractIds( id_list )

  id_list = [ '/api/v1/ns/model:sdf' ]
  with pytest.raises( ValueError ):
    uri.extractIds( id_list )

  id_list = [ '/api/v1/ns/model' ]
  with pytest.raises( ValueError ):
    uri.extractIds( id_list )

  id_list = [ '/api/v1/ns/model:sdf:', '/api/v1/ns/model', '/api/v1/ns/model:rfv:' ]
  with pytest.raises( ValueError ):
    uri.extractIds( id_list )
Exemple #3
0
    def __init__(
        self,
        host,
        root_path,
        proxy=None,
        verify_ssl=True,
        retry_event=None
    ):  # retry_event should be an Event Object, use to cancel retry loops, if the event get's set the retry loop will throw the most recent Exception it ignored
        super().__init__()
        self.retry_event = retry_event

        if not host.startswith(('http:', 'https:')):
            raise ValueError('hostname must start with http(s):')

        if host[-1] == '/':
            raise ValueError('hostname must not end with "/"')

        self.proxy = proxy
        self.host = host
        logging.debug(
            'cinp: new client host: "{0}", root_path: "{1}", via: "{2}"'.
            format(self.host, root_path, self.proxy))

        self.uri = URI(root_path)

        self.opener = request.OpenerDirector()

        if self.proxy:  # not doing 'is not None', so empty strings don't try and proxy   # have a proxy option to take it from the envrionment vars
            self.opener.add_handler(
                request.ProxyHandler({
                    'http': self.proxy,
                    'https': self.proxy
                }))
        else:
            self.opener.add_handler(request.ProxyHandler({}))

        self.opener.add_handler(request.HTTPHandler())
        if hasattr(http.client, 'HTTPSConnection'):
            if not verify_ssl:
                self.opener.add_handler(
                    request.HTTPSHandler(
                        context=ssl._create_unverified_context()))
            else:
                self.opener.add_handler(request.HTTPSHandler())

        self.opener.add_handler(request.UnknownHandler())

        self.opener.addheaders = [
            ('User-Agent',
             'python CInP client {0}'.format(__CLIENT_VERSION__)),
            ('Accepts', 'application/json'), ('Accept-Charset', 'utf-8'),
            ('CInP-Version', __CINP_VERSION__)
        ]
Exemple #4
0
    def uploadFile(self, uri, filepath, filename=None, cb=None, timeout=30):
        """
    filepath can be a string of the path name or a file object.  If a file object
    either specify the filename or make sure your file object exposes the attribute
    'name'.  Also if file object, must be opened in binary mode, ie: 'rb'

    NOTE: this is not a CInP function, but a conviance function for uploading large files.
    """
        uri_parser = URI('/')
        try:  # TODO: There has to be a better way to validate this uri
            (namespace, model, action, id_list, _) = uri_parser.split(uri)
        except ValueError as e:
            raise InvalidRequest(str(e))

        if action is not None or id_list is not None:
            raise InvalidRequest(
                'file upload target can\'t be an action nor have ids')

        if isinstance(filepath, str):
            if filename is None:
                filename = os.path.basename(filepath)

            file_reader = _readerWrapper(open(filepath, 'rb'), cb)

        else:
            if filename is None:
                filename = os.path.basename(filepath.name)

            file_reader = _readerWrapper(filepath, cb)

        header_map = {
            'Content-Disposition': 'inline: filename="{0}"'.format(filename),
            'Content-Length': len(file_reader)
        }

        (http_code, data,
         _) = self._request('UPLOAD',
                            uri_parser.build(namespace, model),
                            data=file_reader,
                            header_map=header_map,
                            timeout=timeout)

        if http_code != 202:
            logging.warning(
                'cinp: Unexpected HTTP Code "{0}" for File Upload'.format(
                    http_code))
            raise ResponseError(
                'Unexpected HTTP Code "{0}" for File Upload'.format(http_code))

        return data['uri']
Exemple #5
0
def test_getElement():
  uri = URI( root_path='/api/' )
  root_ns = Namespace( name=None, version='0.0', root_path='/api/', converter=None )
  ns2 = Namespace( name='ns2', version='0.1', converter=None )
  ns3 = Namespace( name='ns3', version='0.2', converter=None )
  ns2_2 = Namespace( name='ns2_2', version='0.1', converter=None )
  root_ns.addElement( ns2 )
  root_ns.addElement( ns3 )
  ns2.addElement( ns2_2 )
  mdl1 = Model( name='mdl1', field_list={}, transaction_class=TestTransaction )
  mdl2 = Model( name='mdl2', field_list={}, transaction_class=TestTransaction )
  root_ns.addElement( mdl1 )
  ns2_2.addElement( mdl2 )
  act1 = Action( name='act1', return_paramater=Paramater( type='String' ), paramater_list=[ Paramater( name='bob', type='Float' ) ], static=False, func=fake_func )
  act2 = Action( name='act2', return_paramater=Paramater( type='String' ), paramater_list=[ Paramater( name='stuff', type='Boolean' ) ], func=fake_func )
  mdl1.addAction( act1 )
  mdl2.addAction( act2 )

  assert root_ns.getElement( uri.split( '/api/', root_optional=True ) ) == root_ns
  assert root_ns.getElement( uri.split( '/api/ns2/', root_optional=True ) ) == ns2
  assert root_ns.getElement( uri.split( '/api/ns3/', root_optional=True ) ) == ns3
  assert root_ns.getElement( uri.split( '/api/ns2/ns2_2/', root_optional=True ) ) == ns2_2
  assert root_ns.getElement( uri.split( '/', root_optional=True ) ) == root_ns
  assert root_ns.getElement( uri.split( '/ns2/', root_optional=True ) ) == ns2
  assert root_ns.getElement( uri.split( '/ns3/', root_optional=True ) ) == ns3
  assert root_ns.getElement( uri.split( '/ns2/ns2_2/', root_optional=True ) ) == ns2_2
  assert root_ns.getElement( uri.split( '/api/mdl1', root_optional=True ) ) == mdl1
  assert root_ns.getElement( uri.split( '/api/ns2/ns2_2/mdl2', root_optional=True ) ) == mdl2
  assert root_ns.getElement( uri.split( '/mdl1', root_optional=True ) ) == mdl1
  assert root_ns.getElement( uri.split( '/ns2/ns2_2/mdl2', root_optional=True ) ) == mdl2
  assert root_ns.getElement( uri.split( '/api/mdl1(act1)', root_optional=True ) ) == act1
  assert root_ns.getElement( uri.split( '/api/ns2/ns2_2/mdl2(act2)', root_optional=True ) ) == act2
  assert root_ns.getElement( uri.split( '/mdl1(act1)', root_optional=True ) ) == act1
  assert root_ns.getElement( uri.split( '/ns2/ns2_2/mdl2(act2)', root_optional=True ) ) == act2

  with pytest.raises( ValueError ):
    root_ns.getElement( '/api/' )

  assert root_ns.getElement( uri.split( '/api/nsX/' ) ) is None
  assert root_ns.getElement( uri.split( '/api/ns2/mdlX' ) ) is None
  assert root_ns.getElement( uri.split( '/api/mdl1(actX)' ) ) is None
Exemple #6
0
def test_splituri_builduri():  # TODO: test invlid URIs, mabey remove some tests from client_test that are just checking the URI
  uri = URI( '/api/v1/' )

  ( ns, model, action, id_list, multi ) = uri.split( '/api/v1/' )
  assert ns == []
  assert model is None
  assert id_list is None
  assert action is None
  assert multi is False
  assert uri.build( ns, model, action, id_list ) == '/api/v1/'
  ns = None
  assert uri.build( ns, model, action, id_list ) == '/api/v1/'

  ( ns, model, action, id_list, multi ) = uri.split( '/api/v1/ns/' )
  assert ns == [ 'ns' ]
  assert model is None
  assert id_list is None
  assert action is None
  assert multi is False
  assert uri.build( ns, model, action, id_list ) == '/api/v1/ns/'
  ns = 'ns'
  assert uri.build( ns, model, action, id_list ) == '/api/v1/ns/'

  ( ns, model, action, id_list, multi ) = uri.split( '/api/v1/ns/model' )
  assert ns == [ 'ns' ]
  assert model == 'model'
  assert id_list is None
  assert action is None
  assert multi is False
  assert uri.build( ns, model, action, id_list ) == '/api/v1/ns/model'
  id_list = []
  assert uri.build( ns, model, action, id_list ) == '/api/v1/ns/model'

  ( ns, model, action, id_list, multi ) = uri.split( '/api/v1/ns/ns2/' )
  assert ns == [ 'ns', 'ns2' ]
  assert model is None
  assert id_list is None
  assert action is None
  assert multi is False
  assert uri.build( ns, model, action, id_list ) == '/api/v1/ns/ns2/'

  ( ns, model, action, id_list, multi ) = uri.split( '/api/v1/ns/ns2/model' )
  assert ns == [ 'ns', 'ns2' ]
  assert model == 'model'
  assert id_list is None
  assert action is None
  assert multi is False
  assert uri.build( ns, model, action, id_list ) == '/api/v1/ns/ns2/model'

  ( ns, model, action, id_list, multi ) = uri.split( '/api/v1/ns/model::' )
  assert ns == [ 'ns' ]
  assert model == 'model'
  assert id_list == [ '' ]
  assert action is None
  assert multi is False
  assert uri.build( ns, model, action, id_list ) == '/api/v1/ns/model::'
  id_list = ''
  assert uri.build( ns, model, action, id_list ) == '/api/v1/ns/model::'

  ( ns, model, action, id_list, multi ) = uri.split( '/api/v1/ns/model:ghj:' )
  assert ns == [ 'ns' ]
  assert model == 'model'
  assert id_list == [ 'ghj' ]
  assert action is None
  assert multi is False
  assert uri.build( ns, model, action, id_list ) == '/api/v1/ns/model:ghj:'
  id_list = 'ghj'
  assert uri.build( ns, model, action, id_list ) == '/api/v1/ns/model:ghj:'

  ( ns, model, action, id_list, multi ) = uri.split( '/api/v1/ns/model:ghj:dsf:sfe:' )
  assert ns == [ 'ns' ]
  assert model == 'model'
  assert id_list == [ 'ghj', 'dsf', 'sfe' ]
  assert action is None
  assert multi is True
  assert uri.build( ns, model, action, id_list ) == '/api/v1/ns/model:ghj:dsf:sfe:'

  ( ns, model, action, id_list, multi ) = uri.split( '/api/v1/ns/model(action)' )
  assert ns == [ 'ns' ]
  assert model == 'model'
  assert id_list is None
  assert action == 'action'
  assert multi is False
  assert uri.build( ns, model, action, id_list ) == '/api/v1/ns/model(action)'

  ( ns, model, action, id_list, multi ) = uri.split( '/api/v1/ns/model:sdf:(action)' )
  assert ns == [ 'ns' ]
  assert model == 'model'
  assert id_list == [ 'sdf' ]
  assert action == 'action'
  assert multi is False
  assert uri.build( ns, model, action, id_list ) == '/api/v1/ns/model:sdf:(action)'

  ( ns, model, action, id_list, multi ) = uri.split( '/api/v1/ns/model:sdf:eed:(action)' )
  assert ns == [ 'ns' ]
  assert model == 'model'
  assert id_list == [ 'sdf', 'eed' ]
  assert action == 'action'
  assert multi is True
  assert uri.build( ns, model, action, id_list ) == '/api/v1/ns/model:sdf:eed:(action)'

  ( ns, model, action, id_list, multi ) = uri.split( '/api/v1/', root_optional=True )
  assert ns == []
  assert model is None
  assert id_list is None
  assert action is None
  assert multi is False
  assert uri.build( ns, model, action, id_list ) == '/api/v1/'
  assert uri.build( ns, model, action, id_list, in_root=False ) == '/'

  with pytest.raises( ValueError ):
    ( ns, model, action, id_list, multi ) = uri.split( '/', root_optional=False )
  ( ns, model, action, id_list, multi ) = uri.split( '/', root_optional=True )
  assert ns == []
  assert model is None
  assert id_list is None
  assert action is None
  assert multi is False
  assert uri.build( ns, model, action, id_list ) == '/api/v1/'
  assert uri.build( ns, model, action, id_list, in_root=False ) == '/'

  ( ns, model, action, id_list, multi ) = uri.split( '/api/v1/ns/', root_optional=True )
  assert ns == [ 'ns' ]
  assert model is None
  assert id_list is None
  assert action is None
  assert multi is False
  assert uri.build( ns, model, action, id_list ) == '/api/v1/ns/'
  assert uri.build( ns, model, action, id_list, in_root=False ) == '/ns/'

  with pytest.raises( ValueError ):
    ( ns, model, action, id_list, multi ) = uri.split( '/ns/', root_optional=False )
  ( ns, model, action, id_list, multi ) = uri.split( '/ns/', root_optional=True )
  assert ns == [ 'ns' ]
  assert model is None
  assert id_list is None
  assert action is None
  assert multi is False
  assert uri.build( ns, model, action, id_list ) == '/api/v1/ns/'
  assert uri.build( ns, model, action, id_list, in_root=False ) == '/ns/'
Exemple #7
0
def test_not_allowed_verbs():
  server = Server( root_path='/api/', root_version='0.0', debug=True )
  ns1 = Namespace( name='ns1', version='0.1', converter=Converter( URI( '/api/' ) ) )
  ns1.checkAuth = lambda user, verb, id_list: True
  field_list = []
  field_list.append( Field( name='field1', type='String', length=50 ) )
  model1 = Model( name='model1', field_list=field_list, not_allowed_verb_list=[], transaction_class=TestTransaction )
  model2 = Model( name='model2', field_list=field_list, not_allowed_verb_list=[ 'GET', 'LIST', 'CALL', 'CREATE', 'UPDATE', 'DELETE', 'DESCRIBE' ], transaction_class=TestTransaction )
  model1.checkAuth = lambda user, verb, id_list: True
  model2.checkAuth = lambda user, verb, id_list: True
  action1 = Action( name='act', return_paramater=Paramater( type='String' ), func=fake_func )
  action2 = Action( name='act', return_paramater=Paramater( type='String' ), func=fake_func )
  action1.checkAuth = lambda user, verb, id_list: True
  action2.checkAuth = lambda user, verb, id_list: True
  model1.addAction( action1 )
  model2.addAction( action2 )
  ns1.addElement( model1 )
  ns1.addElement( model2 )
  server.registerNamespace( '/', ns1 )

  with pytest.raises( ValueError ):
    Model( name='modelX', field_list=[], not_allowed_verb_list=[ 'OPTIONS' ], transaction_class=TestTransaction )

  with pytest.raises( ValueError ):
    Model( name='modelX', field_list=[], not_allowed_verb_list=[ 'ASDF' ], transaction_class=TestTransaction )

  req = Request( 'OPTIONS', '/api/ns1/model1', { 'CINP-VERSION': __CINP_VERSION__ } )
  res = server.handle( req )
  assert res.http_code == 200

  req = Request( 'OPTIONS', '/api/ns1/model2', { 'CINP-VERSION': __CINP_VERSION__ } )
  res = server.handle( req )
  assert res.http_code == 200

  req = Request( 'DESCRIBE', '/api/ns1/model1', { 'CINP-VERSION': __CINP_VERSION__ } )
  res = server.handle( req )
  assert res.http_code == 200

  req = Request( 'DESCRIBE', '/api/ns1/model2', { 'CINP-VERSION': __CINP_VERSION__ } )
  res = server.handle( req )
  assert res.http_code == 403

  req = Request( 'GET', '/api/ns1/model1:asd:', { 'CINP-VERSION': __CINP_VERSION__ } )
  res = server.handle( req )
  assert res.http_code == 200

  req = Request( 'GET', '/api/ns1/model2:asd:', { 'CINP-VERSION': __CINP_VERSION__ } )
  res = server.handle( req )
  assert res.http_code == 403

  req = Request( 'LIST', '/api/ns1/model1', { 'CINP-VERSION': __CINP_VERSION__ } )
  res = server.handle( req )
  assert res.http_code == 200

  req = Request( 'LIST', '/api/ns1/model2', { 'CINP-VERSION': __CINP_VERSION__ } )
  res = server.handle( req )
  assert res.http_code == 403

  req = Request( 'CREATE', '/api/ns1/model1', { 'CINP-VERSION': __CINP_VERSION__ } )
  req.data = { 'field1': 'stuff' }
  res = server.handle( req )
  assert res.http_code == 201

  req = Request( 'CREATE', '/api/ns1/model2', { 'CINP-VERSION': __CINP_VERSION__ } )
  req.data = { 'field1': 'stuff' }
  res = server.handle( req )
  assert res.http_code == 403

  req = Request( 'UPDATE', '/api/ns1/model1:sdf:', { 'CINP-VERSION': __CINP_VERSION__ } )
  req.data = { 'field1': 'stuff' }
  res = server.handle( req )
  assert res.http_code == 200

  req = Request( 'UPDATE', '/api/ns1/model2:sdf:', { 'CINP-VERSION': __CINP_VERSION__ } )
  req.data = { 'field1': 'stuff' }
  res = server.handle( req )
  assert res.http_code == 403

  req = Request( 'DELETE', '/api/ns1/model1:asd:', { 'CINP-VERSION': __CINP_VERSION__ } )
  res = server.handle( req )
  assert res.http_code == 200

  req = Request( 'DELETE', '/api/ns1/model2:asd:', { 'CINP-VERSION': __CINP_VERSION__ } )
  res = server.handle( req )
  assert res.http_code == 403

  req = Request( 'CALL', '/api/ns1/model1(act)', { 'CINP-VERSION': __CINP_VERSION__ } )
  res = server.handle( req )
  assert res.http_code == 200

  req = Request( 'CALL', '/api/ns1/model2(act)', { 'CINP-VERSION': __CINP_VERSION__ } )
  res = server.handle( req )
  assert res.http_code == 403
Exemple #8
0
    def getFile(self,
                uri,
                target_dir='/tmp',
                file_object=None,
                cb=None,
                timeout=30,
                chunk_size=(4096 * 1024)):
        """
    if file_object is defined:
       The file contense are written to it and the filename as specified by the
       server is returned, None is returned if not filename is detected.  The
       file_object is not closed. file_object must be opened with the 'b' attribute.

    Otherwise a file is created in target_dir, and the full path is returned.  If the
      filename is not specified by the server, and a random filename is chosen.
      WARNING: there isn't checking done to make sure the target file does not allready
      exist, there is a possibility it could clober something that allready exists.
      we do make sure the filename fits a regex pattern that prevents it from escaping
      the target_dir.  The "filename" as sent by the server is the "model" of the uri.
      make sure target_dir exists before calling getFile
    """

        uri_parser = URI('/')
        try:  # TODO: There has to be a better way to validate this uri
            (_, filename, _, _, _) = uri_parser.split(uri)
        except ValueError as e:
            raise InvalidRequest(str(e))

        # Due to the return value we have to do our own request, this is pretty much a stright GET
        url = '{0}{1}'.format(self.host, uri)
        req = request.Request(url)
        req.get_method = lambda: 'GET'
        try:
            resp = self.opener.open(req, timeout=timeout)

        except request.HTTPError as e:
            raise ResponseError('HTTPError "{0}"'.format(e))

        except request.URLError as e:
            if isinstance(e.reason, socket.timeout):
                raise Timeout(
                    'Request Timeout after {0} seconds'.format(timeout))

            raise ResponseError('URLError "{0}" for "{1}" via "{2}"'.format(
                e, url, self.proxy))

        http_code = resp.code
        if http_code != 200:
            logging.warning(
                'cinp: Unexpected HTTP Code "{0}" for File Get'.format(
                    http_code))
            raise ResponseError(
                'Unexpected HTTP Code "{0}" for File Get'.format(http_code))

        try:
            size = resp.headers['Content-Length']
        except KeyError:
            size = 0

        if file_object is not None:
            file_writer = file_object

        else:
            if filename is None:
                file_writer = NamedTemporaryFile(dir=target_dir, mode='wb')
                filename = file_writer.name

            else:
                filename = os.path.join(target_dir, filename)
                file_writer = open(filename, 'wb')

        buff = resp.read(chunk_size)
        while buff:
            file_writer.write(buff)
            if cb:
                cb(file_writer.tell(), size)
            buff = resp.read(chunk_size)

        resp.close()

        if file_object is not None:
            return filename

        else:
            file_writer.close()
            return filename