Dynamic import of grpc-protobuf from given directory (proto_dir)
    service_name should be provided only in the case of conflicting method names (two methods with the same name in difference services).
    Return stub_class, request_class, response_class
    ! We need response_class only for json payload encoding !

def import_protobuf_from_dir(proto_dir, method_name, service_name = None):
    """
    Dynamic import of grpc-protobuf from given directory (proto_dir)
    service_name should be provided only in the case of conflicting method names (two methods with the same name in difference services).
    Return stub_class, request_class, response_class
    ! We need response_class only for json payload encoding !
    """
    proto_dir = Path(proto_dir)
    # <SERVICE>_pb2_grpc.py import <SERVICE>_pb2.py so we are forced to add proto_dir to path
    sys.path.append(str(proto_dir))    
    grpc_pyfiles = [str(os.path.basename(p)) for p in proto_dir.glob("*_pb2_grpc.py")]
    
    good_rez = []
    for grpc_pyfile in grpc_pyfiles:
        is_found, rez = _import_protobuf_from_file(grpc_pyfile, method_name, service_name);
        if (is_found): good_rez.append(rez) 
    if (len(good_rez) == 0):
        raise Exception("Error while loading protobuf. Cannot find method=%s"%method_name)
    if (len(good_rez) > 1):
        if (service_name):
            raise Exception("Error while loading protobuf. Found method %s.%s in multiply .proto files. We don't support packages yet!"%(service_name, method_name))
        else:
            raise Exception("Error while loading protobuf. Found method %s in multiply .proto files. You could try to specify service_name."%method_name)
    return good_rez[0]