from oci.util import formatted_flat_dict, NONE_SENTINEL, value_allowed_none_or_none_sentinel  # noqa: F401
from oci.decorators import init_model_state_from_kwargs

@init_model_state_from_kwargs
class CreateRoutingPolicyDetails(object):
    """
    An ordered list of routing rules.

    **Warning:** Oracle recommends that you avoid using any confidential information when you supply string values using the API.
    """

    #: A constant which can be used with the condition_language_version property of a CreateRoutingPolicyDetails.
    #: This constant has a value of "V1"
    CONDITION_LANGUAGE_VERSION_V1 = "V1"

    def __init__(self, **kwargs):
        """
        Initializes a new CreateRoutingPolicyDetails object with values from keyword arguments.
        The following keyword arguments are supported (corresponding to the getters/setters of this class):

        :param name:
            The value to assign to the name property of this CreateRoutingPolicyDetails.
        :type name: str

        :param condition_language_version:
            The value to assign to the condition_language_version property of this CreateRoutingPolicyDetails.
            Allowed values for this property are: "V1"
        :type condition_language_version: str

        :param rules:
            The value to assign to the rules property of this CreateRoutingPolicyDetails.
        :type rules: list[oci.load_balancer.models.RoutingRule]

        """
        self.swagger_types = {
            'name': 'str',
            'condition_language_version': 'str',
            'rules': 'list[RoutingRule]'
        }

        self.attribute_map = {
            'name': 'name',
            'condition_language_version': 'conditionLanguageVersion',
            'rules': 'rules'
        }

        self._name = None
        self._condition_language_version = None
        self._rules = None

    @property
    def name(self):
        """
        **[Required]** Gets the name of this CreateRoutingPolicyDetails.
        The name for this list of routing rules. It must be unique and it cannot be changed. Avoid entering
        confidential information.

        Example: `example_routing_rules`

        :return: The name of this CreateRoutingPolicyDetails.
        :rtype: str
        """

    @name.setter
    def name(self, name):
        """
        Sets the name of this CreateRoutingPolicyDetails.
        The name for this list of routing rules. It must be unique and it cannot be changed. Avoid entering
        confidential information.

        Example: `example_routing_rules`

        :param name: The name of this CreateRoutingPolicyDetails.
        :type: str
        """
        self._name = name

    @property
    def condition_language_version(self):
        """
        **[Required]** Gets the condition_language_version of this CreateRoutingPolicyDetails.
        The version of the language in which `condition` of `rules` are composed.

        Allowed values for this property are: "V1"

        :return: The condition_language_version of this CreateRoutingPolicyDetails.
        :rtype: str
        """
        return self._condition_language_version

    @condition_language_version.setter
    def condition_language_version(self, condition_language_version):
        """
        Sets the condition_language_version of this CreateRoutingPolicyDetails.
        The version of the language in which `condition` of `rules` are composed.

        :param condition_language_version: The condition_language_version of this CreateRoutingPolicyDetails.
        :type: str
        """
        allowed_values = ["V1"]
        if not value_allowed_none_or_none_sentinel(condition_language_version, allowed_values):
            raise ValueError(
                "Invalid value for `condition_language_version`, must be None or one of {0}"
                .format(allowed_values)
            )
        self._condition_language_version = condition_language_version

    @property
    def rules(self):
        """
        **[Required]** Gets the rules of this CreateRoutingPolicyDetails.
        The list of routing rules.

        :return: The rules of this CreateRoutingPolicyDetails.
        :rtype: list[oci.load_balancer.models.RoutingRule]
        """
        return self._rules

    @rules.setter
    def rules(self, rules):
        """
        Sets the rules of this CreateRoutingPolicyDetails.
        The list of routing rules.

        :param rules: The rules of this CreateRoutingPolicyDetails.
        :type: list[oci.load_balancer.models.RoutingRule]
        """
        self._rules = rules

    def __repr__(self):
        return formatted_flat_dict(self)

    def __eq__(self, other):
        if other is None:
            return False

        return self.__dict__ == other.__dict__

    def __ne__(self, other):
        return not self == other


def __init__(self, cfg, args, image_path, save_filename, im_width, im_height):

import os
import cv2
import time
import argparse
import torch
import warnings
import numpy as np

from detector import build_detector
from deep_sort import build_tracker
from utils.draw import draw_boxes
from utils.parser import get_config
from utils.log import get_logger
from utils.io import write_results
import glob

class VideoTracker(object):
    def __init__(self, cfg, args, video_path):
        self.cfg = cfg
        self.args = args
        self.video_path = video_path
        self.logger = get_logger("root")

        use_cuda = args.use_cuda and torch.cuda.is_available()
        if not use_cuda:
            warnings.warn("Running in cpu mode which maybe very slow!", UserWarning)

        if args.display:
            cv2.namedWindow("test", cv2.WINDOW_NORMAL)
            cv2.resizeWindow("test", args.display_width, args.display_height)

        if args.cam != -1:
            print("Using webcam " + str(args.cam))
            self.vdo = cv2.VideoCapture(args.cam)
        else:
            self.vdo = cv2.VideoCapture()
        self.detector = build_detector(cfg, use_cuda=use_cuda, detector_name='EfficientDet')
        self.deepsort = build_tracker(cfg, use_cuda=use_cuda)

    def __enter__(self):
        if self.args.cam != -1:
            ret, frame = self.vdo.read()
            assert ret, "Error: Camera error"
            self.im_width = frame.shape[0]
            self.im_height = frame.shape[1]

        else:
            assert os.path.isfile(self.video_path), "Path error"
            self.vdo.open(self.video_path)
            self.im_width = int(self.vdo.get(cv2.CAP_PROP_FRAME_WIDTH))
            self.im_height = int(self.vdo.get(cv2.CAP_PROP_FRAME_HEIGHT))
            assert self.vdo.isOpened()

        if self.args.save_path:
            os.makedirs(self.args.save_path, exist_ok=True)

            # path of saved video and results
            self.save_video_path = os.path.join(self.args.save_path, "results.avi")
            self.save_results_path = os.path.join(self.args.save_path, "results.txt")

            # create video writer
            fourcc =  cv2.VideoWriter_fourcc(*'MJPG')
            self.writer = cv2.VideoWriter(self.save_video_path, fourcc, 20, (self.im_width,self.im_height))

            # logging
            self.logger.info("Save results to {}".format(self.args.save_path))

        return self

    def __exit__(self, exc_type, exc_value, exc_traceback):
        if exc_type:
            print(exc_type, exc_value, exc_traceback)

    def run(self):
        results = []
        idx_frame = 0
        while self.vdo.grab():
            idx_frame += 1
            if idx_frame % self.args.frame_interval:
                continue

            start = time.time()
            _, ori_im = self.vdo.retrieve()
            im = cv2.cvtColor(ori_im, cv2.COLOR_BGR2RGB)
            im = cv2.cvtColor(im, cv2.COLOR_RGB2BGR)
            # do detection
            bbox_xywh, cls_conf, cls_ids = self.detector(im)

            # select person class
            mask = cls_ids==0

            bbox_xywh = bbox_xywh[mask]
            # bbox dilation just in case bbox too small, delete this line if using a better pedestrian detector
            bbox_xywh[:,3:] *= 1.2
            cls_conf = cls_conf[mask]
            im = cv2.cvtColor(ori_im, cv2.COLOR_BGR2RGB)
            # do tracking
            outputs = self.deepsort.update(bbox_xywh, cls_conf, im)

            # draw boxes for visualization
            if len(outputs) > 0:
                bbox_tlwh = []
                bbox_xyxy = outputs[:,:4]
                identities = outputs[:,-1]
                ori_im = draw_boxes(ori_im, bbox_xyxy, identities)

                for bb_xyxy in bbox_xyxy:
                    bbox_tlwh.append(self.deepsort._xyxy_to_tlwh(bb_xyxy))

                results.append((idx_frame-1, bbox_tlwh, identities))

            end = time.time()

            if self.args.display:
                cv2.imshow("test", ori_im)
                cv2.waitKey(1)

            if self.args.save_path:
                self.writer.write(ori_im)

            # save results
            write_results(self.save_results_path, results, 'mot')

            # logging
            self.logger.info("time: {:.03f}s, fps: {:.03f}, detection numbers: {}, tracking numbers: {}" \
                            .format(end-start, 1/(end-start), bbox_xywh.shape[0], len(outputs)))

class ImageTracker(object):

self.cfg = cfg
        self.args = args
        self.image_path = image_path

        self.logger = get_logger("root")
        self.save_filename = save_filename
        self.im_width = im_width
        self.im_height = im_height

        use_cuda = args.use_cuda and torch.cuda.is_available()
        if not use_cuda:
            warnings.warn("Running in cpu mode which maybe very slow!", UserWarning)

        if args.display:
            cv2.namedWindow("test", cv2.WINDOW_NORMAL)
            cv2.resizeWindow("test", args.display_width, args.display_height)

        self.detector = build_detector(cfg, use_cuda=use_cuda, detector_name='Rcnn')
        self.deepsort = build_tracker(cfg, use_cuda=use_cuda)

    def __enter__(self):

        image_format = ['.jpg', '.jpeg', '.png', '.tif']
        self.images = sorted(glob.glob('%s/*.*' % self.image_path))
        self.images = list(filter(lambda x: os.path.splitext(x)[1].lower() in image_format, self.images))
        if self.args.save_path:
            os.makedirs(self.args.save_path, exist_ok=True)

            # path of saved video and results
            self.save_video_path = os.path.join(self.args.save_path, self.save_filename+".avi")
            self.save_results_path = os.path.join(self.args.save_path, self.save_filename+'.txt')
            # create video writer
            fourcc =  cv2.VideoWriter_fourcc(*'MJPG')
            self.writer = cv2.VideoWriter(self.save_video_path, fourcc, 20, (self.im_width,self.im_height))

            # logging
            self.logger.info("Save results to {}".format(self.args.save_path))

        return self

    def __exit__(self, exc_type, exc_value, exc_traceback):
        if exc_type:
            print(exc_type, exc_value, exc_traceback)

    def run(self):
        results = []
        idx_frame = 0
        for img_file in self.images:
            print(img_file)
            idx_frame += 1

            start = time.time()
            ori_im = cv2.imread(img_file)
            im = ori_im
            # do detection
            bbox_xywh, cls_conf, cls_ids = self.detector(im)

            # select person class
            mask = cls_ids==0
            bbox_xywh = bbox_xywh[mask]
            # bbox dilation just in case bbox too small, delete this line if using a better pedestrian detector
            cls_conf = cls_conf[mask]
            im = cv2.cvtColor(ori_im, cv2.COLOR_BGR2RGB)
            # do tracking
            outputs = self.deepsort.update(bbox_xywh, cls_conf, im)

            # draw boxes for visualization
            if len(outputs) > 0:
                bbox_tlwh = []
                bbox_xyxy = outputs[:,:4]
                identities = outputs[:,-1]
                ori_im = draw_boxes(ori_im, bbox_xyxy, identities)

                for bb_xyxy in bbox_xyxy:
                    bbox_tlwh.append(self.deepsort._xyxy_to_tlwh(bb_xyxy))

                results.append((idx_frame-2, bbox_tlwh, identities))

            end = time.time()

            if self.args.display:
                cv2.imshow("test", ori_im)
                cv2.waitKey(1)

            if self.args.save_path:
                self.writer.write(ori_im)
            if self.args.display:
                cv2.imshow("test", ori_im)
                cv2.waitKey(1)
            # save results
            write_results(self.save_results_path, results, 'mot')

            # logging
            self.logger.info("time: {:.03f}s, fps: {:.03f}, detection numbers: {}, tracking numbers: {}" \
                            .format(end-start, 1/(end-start), bbox_xywh.shape[0], len(outputs)))

def parse_args():
    parser = argparse.ArgumentParser()
    parser.add_argument("--config_detection", type=str, default="./configs/rcnn.yaml")
    parser.add_argument("--config_deepsort", type=str, default="./configs/deep_sort.yaml")
    parser.add_argument("--display", action="store_true")
    parser.add_argument("--frame_interval", type=int, default=1)
    parser.add_argument("--display_width", type=int, default=800)
    parser.add_argument("--display_height", type=int, default=600)
    parser.add_argument("--save_path", type=str, default="./outputs/")
    parser.add_argument("--cpu", dest="use_cuda", action="store_false", default=True)
    parser.add_argument("--camera", action="store", dest="cam", type=int, default="-1")
    return parser.parse_args()

if __name__=="__main__":
    os.environ['CUDA_VISIBLE_DEVICES'] = '0'
    args = parse_args()
    cfg = get_config()
    cfg.merge_from_file(args.config_detection)
    cfg.merge_from_file(args.config_deepsort)

    with ImageTracker(cfg, args, r'/media/shenfei/shensdd/deep_sort_new/detector/Pedestron/datasets/zhongxing/testB/Track2/new_img1', 'Track2', 1550, 734) as img_trk:
        img_trk.run()


import os
import cv2
import time
import argparse
import torch
import warnings
import numpy as np

from detector import build_detector
from deep_sort import build_tracker
from utils.draw import draw_boxes
from utils.parser import get_config
from utils.log import get_logger
from utils.io import write_results
import glob

class VideoTracker(object):
    def __init__(self, cfg, args, video_path):
        self.cfg = cfg
        self.args = args
        self.video_path = video_path
        self.logger = get_logger("root")

        use_cuda = args.use_cuda and torch.cuda.is_available()
        if not use_cuda:
            warnings.warn("Running in cpu mode which maybe very slow!", UserWarning)

        if args.display:
            cv2.namedWindow("test", cv2.WINDOW_NORMAL)
            cv2.resizeWindow("test", args.display_width, args.display_height)

        if args.cam != -1:
            print("Using webcam " + str(args.cam))
            self.vdo = cv2.VideoCapture(args.cam)
        else:
            self.vdo = cv2.VideoCapture()
        self.detector = build_detector(cfg, use_cuda=use_cuda, detector_name='EfficientDet')
        self.deepsort = build_tracker(cfg, use_cuda=use_cuda)

    def __enter__(self):
        if self.args.cam != -1:
            ret, frame = self.vdo.read()
            assert ret, "Error: Camera error"
            self.im_width = frame.shape[0]
            self.im_height = frame.shape[1]

        else:
            assert os.path.isfile(self.video_path), "Path error"
            self.vdo.open(self.video_path)
            self.im_width = int(self.vdo.get(cv2.CAP_PROP_FRAME_WIDTH))
            self.im_height = int(self.vdo.get(cv2.CAP_PROP_FRAME_HEIGHT))
            assert self.vdo.isOpened()

        if self.args.save_path:
            os.makedirs(self.args.save_path, exist_ok=True)

            # path of saved video and results
            self.save_video_path = os.path.join(self.args.save_path, "results.avi")
            self.save_results_path = os.path.join(self.args.save_path, "results.txt")

            # create video writer
            fourcc =  cv2.VideoWriter_fourcc(*'MJPG')
            self.writer = cv2.VideoWriter(self.save_video_path, fourcc, 20, (self.im_width,self.im_height))

            # logging
            self.logger.info("Save results to {}".format(self.args.save_path))

        return self

    def __exit__(self, exc_type, exc_value, exc_traceback):
        if exc_type:
            print(exc_type, exc_value, exc_traceback)

    def run(self):
        results = []
        idx_frame = 0
        while self.vdo.grab():
            idx_frame += 1
            if idx_frame % self.args.frame_interval:
                continue

            start = time.time()
            _, ori_im = self.vdo.retrieve()
            im = cv2.cvtColor(ori_im, cv2.COLOR_BGR2RGB)
            im = cv2.cvtColor(im, cv2.COLOR_RGB2BGR)
            # do detection
            bbox_xywh, cls_conf, cls_ids = self.detector(im)

            # select person class
            mask = cls_ids==0

            bbox_xywh = bbox_xywh[mask]
            # bbox dilation just in case bbox too small, delete this line if using a better pedestrian detector
            bbox_xywh[:,3:] *= 1.2
            cls_conf = cls_conf[mask]
            im = cv2.cvtColor(ori_im, cv2.COLOR_BGR2RGB)
            # do tracking
            outputs = self.deepsort.update(bbox_xywh, cls_conf, im)

            # draw boxes for visualization
            if len(outputs) > 0:
                bbox_tlwh = []
                bbox_xyxy = outputs[:,:4]
                identities = outputs[:,-1]
                ori_im = draw_boxes(ori_im, bbox_xyxy, identities)

                for bb_xyxy in bbox_xyxy:
                    bbox_tlwh.append(self.deepsort._xyxy_to_tlwh(bb_xyxy))

                results.append((idx_frame-1, bbox_tlwh, identities))

            end = time.time()

            if self.args.display:
                cv2.imshow("test", ori_im)
                cv2.waitKey(1)

            if self.args.save_path:
                self.writer.write(ori_im)

            # save results
            write_results(self.save_results_path, results, 'mot')

            # logging
            self.logger.info("time: {:.03f}s, fps: {:.03f}, detection numbers: {}, tracking numbers: {}" \
                            .format(end-start, 1/(end-start), bbox_xywh.shape[0], len(outputs)))

class ImageTracker(object):
    def __init__(self, cfg, args, image_path, save_filename, im_width, im_height):
        self.cfg = cfg
        self.args = args
        self.image_path = image_path

        self.logger = get_logger("root")
        self.save_filename = save_filename
        self.im_width = im_width
        self.im_height = im_height

        use_cuda = args.use_cuda and torch.cuda.is_available()
        if not use_cuda:
            warnings.warn("Running in cpu mode which maybe very slow!", UserWarning)

        if args.display:
            cv2.namedWindow("test", cv2.WINDOW_NORMAL)
            cv2.resizeWindow("test", args.display_width, args.display_height)

        self.detector = build_detector(cfg, use_cuda=use_cuda, detector_name='Rcnn')
        self.deepsort = build_tracker(cfg, use_cuda=use_cuda)

    def __enter__(self):

        image_format = ['.jpg', '.jpeg', '.png', '.tif']
        self.images = sorted(glob.glob('%s/*.*' % self.image_path))
        self.images = list(filter(lambda x: os.path.splitext(x)[1].lower() in image_format, self.images))
        if self.args.save_path:
            os.makedirs(self.args.save_path, exist_ok=True)

            # path of saved video and results
            self.save_video_path = os.path.join(self.args.save_path, self.save_filename+".avi")
            self.save_results_path = os.path.join(self.args.save_path, self.save_filename+'.txt')
            # create video writer
            fourcc =  cv2.VideoWriter_fourcc(*'MJPG')
            self.writer = cv2.VideoWriter(self.save_video_path, fourcc, 20, (self.im_width,self.im_height))

            # logging
            self.logger.info("Save results to {}".format(self.args.save_path))

        return self

    def __exit__(self, exc_type, exc_value, exc_traceback):

    def run(self):
        results = []
        idx_frame = 0
        for img_file in self.images:
            print(img_file)
            idx_frame += 1

            start = time.time()
            ori_im = cv2.imread(img_file)
            im = ori_im
            # do detection
            bbox_xywh, cls_conf, cls_ids = self.detector(im)

            # select person class
            mask = cls_ids==0
            bbox_xywh = bbox_xywh[mask]
            # bbox dilation just in case bbox too small, delete this line if using a better pedestrian detector
            cls_conf = cls_conf[mask]
            im = cv2.cvtColor(ori_im, cv2.COLOR_BGR2RGB)
            # do tracking
            outputs = self.deepsort.update(bbox_xywh, cls_conf, im)

            # draw boxes for visualization
            if len(outputs) > 0:
                bbox_tlwh = []
                bbox_xyxy = outputs[:,:4]
                identities = outputs[:,-1]
                ori_im = draw_boxes(ori_im, bbox_xyxy, identities)

                for bb_xyxy in bbox_xyxy:
                    bbox_tlwh.append(self.deepsort._xyxy_to_tlwh(bb_xyxy))

                results.append((idx_frame-2, bbox_tlwh, identities))

            end = time.time()

            if self.args.display:
                cv2.imshow("test", ori_im)
                cv2.waitKey(1)

            if self.args.save_path:
                self.writer.write(ori_im)
            if self.args.display:
                cv2.imshow("test", ori_im)
                cv2.waitKey(1)
            # save results
            write_results(self.save_results_path, results, 'mot')

            # logging
            self.logger.info("time: {:.03f}s, fps: {:.03f}, detection numbers: {}, tracking numbers: {}" \
                            .format(end-start, 1/(end-start), bbox_xywh.shape[0], len(outputs)))

def parse_args():
    parser = argparse.ArgumentParser()
    parser.add_argument("--config_detection", type=str, default="./configs/rcnn.yaml")
    parser.add_argument("--config_deepsort", type=str, default="./configs/deep_sort.yaml")
    parser.add_argument("--display", action="store_true")
    parser.add_argument("--frame_interval", type=int, default=1)
    parser.add_argument("--display_width", type=int, default=800)
    parser.add_argument("--display_height", type=int, default=600)
    parser.add_argument("--save_path", type=str, default="./outputs/")
    parser.add_argument("--cpu", dest="use_cuda", action="store_false", default=True)
    parser.add_argument("--camera", action="store", dest="cam", type=int, default="-1")
    return parser.parse_args()

if __name__=="__main__":
    os.environ['CUDA_VISIBLE_DEVICES'] = '0'
    args = parse_args()
    cfg = get_config()
    cfg.merge_from_file(args.config_detection)
    cfg.merge_from_file(args.config_deepsort)

    with ImageTracker(cfg, args, r'/media/shenfei/shensdd/deep_sort_new/detector/Pedestron/datasets/zhongxing/testB/Track2/new_img1', 'Track2', 1550, 734) as img_trk:
        img_trk.run()


import os
import cv2
import time
import argparse
import torch
import warnings
import numpy as np

from detector import build_detector
from deep_sort import build_tracker
from utils.draw import draw_boxes
from utils.parser import get_config
from utils.log import get_logger
from utils.io import write_results
import glob

class VideoTracker(object):
    def __init__(self, cfg, args, video_path):
        self.cfg = cfg
        self.args = args
        self.video_path = video_path
        self.logger = get_logger("root")

        use_cuda = args.use_cuda and torch.cuda.is_available()
        if not use_cuda:
            warnings.warn("Running in cpu mode which maybe very slow!", UserWarning)

        if args.display:
            cv2.namedWindow("test", cv2.WINDOW_NORMAL)
            cv2.resizeWindow("test", args.display_width, args.display_height)

        if args.cam != -1:
            print("Using webcam " + str(args.cam))
            self.vdo = cv2.VideoCapture(args.cam)
        else:
            self.vdo = cv2.VideoCapture()
        self.detector = build_detector(cfg, use_cuda=use_cuda, detector_name='EfficientDet')
        self.deepsort = build_tracker(cfg, use_cuda=use_cuda)

    def __enter__(self):
        if self.args.cam != -1:
            ret, frame = self.vdo.read()
            assert ret, "Error: Camera error"
            self.im_width = frame.shape[0]
            self.im_height = frame.shape[1]

        else:
            assert os.path.isfile(self.video_path), "Path error"
            self.vdo.open(self.video_path)
            self.im_width = int(self.vdo.get(cv2.CAP_PROP_FRAME_WIDTH))
            self.im_height = int(self.vdo.get(cv2.CAP_PROP_FRAME_HEIGHT))
            assert self.vdo.isOpened()

        if self.args.save_path:
            os.makedirs(self.args.save_path, exist_ok=True)

            # path of saved video and results
            self.save_video_path = os.path.join(self.args.save_path, "results.avi")
            self.save_results_path = os.path.join(self.args.save_path, "results.txt")

            # create video writer
            fourcc =  cv2.VideoWriter_fourcc(*'MJPG')
            self.writer = cv2.VideoWriter(self.save_video_path, fourcc, 20, (self.im_width,self.im_height))

            # logging
            self.logger.info("Save results to {}".format(self.args.save_path))

        return self

    def __exit__(self, exc_type, exc_value, exc_traceback):
        if exc_type:
            print(exc_type, exc_value, exc_traceback)

    def run(self):
        results = []
        idx_frame = 0
        while self.vdo.grab():
            idx_frame += 1
            if idx_frame % self.args.frame_interval:
                continue

            start = time.time()
            _, ori_im = self.vdo.retrieve()
            im = cv2.cvtColor(ori_im, cv2.COLOR_BGR2RGB)
            im = cv2.cvtColor(im, cv2.COLOR_RGB2BGR)
            # do detection
            bbox_xywh, cls_conf, cls_ids = self.detector(im)

            # select person class
            mask = cls_ids==0

            bbox_xywh = bbox_xywh[mask]
            # bbox dilation just in case bbox too small, delete this line if using a better pedestrian detector
            bbox_xywh[:,3:] *= 1.2
            cls_conf = cls_conf[mask]
            im = cv2.cvtColor(ori_im, cv2.COLOR_BGR2RGB)
            # do tracking
            outputs = self.deepsort.update(bbox_xywh, cls_conf, im)

            # draw boxes for visualization
            if len(outputs) > 0:
                bbox_tlwh = []
                bbox_xyxy = outputs[:,:4]
                identities = outputs[:,-1]
                ori_im = draw_boxes(ori_im, bbox_xyxy, identities)

                for bb_xyxy in bbox_xyxy:
                    bbox_tlwh.append(self.deepsort._xyxy_to_tlwh(bb_xyxy))

                results.append((idx_frame-1, bbox_tlwh, identities))

            end = time.time()

            if self.args.display:
                cv2.imshow("test", ori_im)
                cv2.waitKey(1)

            if self.args.save_path:
                self.writer.write(ori_im)

            # save results
            write_results(self.save_results_path, results, 'mot')

            # logging
            self.logger.info("time: {:.03f}s, fps: {:.03f}, detection numbers: {}, tracking numbers: {}" \
                            .format(end-start, 1/(end-start), bbox_xywh.shape[0], len(outputs)))

class ImageTracker(object):
    def __init__(self, cfg, args, image_path, save_filename, im_width, im_height):
        self.cfg = cfg
        self.args = args
        self.image_path = image_path

        self.logger = get_logger("root")
        self.save_filename = save_filename
        self.im_width = im_width
        self.im_height = im_height

        use_cuda = args.use_cuda and torch.cuda.is_available()
        if not use_cuda:
            warnings.warn("Running in cpu mode which maybe very slow!", UserWarning)

        if args.display:
            cv2.namedWindow("test", cv2.WINDOW_NORMAL)
            cv2.resizeWindow("test", args.display_width, args.display_height)

        self.detector = build_detector(cfg, use_cuda=use_cuda, detector_name='Rcnn')
        self.deepsort = build_tracker(cfg, use_cuda=use_cuda)

    def __enter__(self):

        image_format = ['.jpg', '.jpeg', '.png', '.tif']
        self.images = sorted(glob.glob('%s/*.*' % self.image_path))
        self.images = list(filter(lambda x: os.path.splitext(x)[1].lower() in image_format, s

        if self.args.save_path:
            os.makedirs(self.args.save_path, exist_ok=True)

            # path of saved video and results
            self.save_video_path = os.path.join(self.args.save_path, self.save_filename+".avi")
            self.save_results_path = os.path.join(self.args.save_path, self.save_filename+'.txt')
            # create video writer
            fourcc =  cv2.VideoWriter_fourcc(*'MJPG')
            self.writer = cv2.VideoWriter(self.save_video_path, fourcc, 20, (self.im_width,self.im_height))

            # logging
            self.logger.info("Save results to {}".format(self.args.save_path))

        return self

    def __exit__(self, exc_type, exc_value, exc_traceback):
        if exc_type:
            print(exc_type, exc_value, exc_traceback)

    def run(self):
        results = []
        idx_frame = 0
        for img_file in self.images:
            print(img_file)
            idx_frame += 1

            start = time.time()
            ori_im = cv2.imread(img_file)
            im = ori_im
            # do detection
            bbox_xywh, cls_conf, cls_ids = self.detector(im)

            # select person class
            mask = cls_ids==0
            bbox_xywh = bbox_xywh[mask]
            # bbox dilation just in case bbox too small, delete this line if using a better pedestrian detector
            cls_conf = cls_conf[mask]
            im = cv2.cvtColor(ori_im, cv2.COLOR_BGR2RGB)
            # do tracking
            outputs = self.deepsort.update(bbox_xywh, cls_conf, im)

            # draw boxes for visualization
            if len(outputs) > 0:
                bbox_tlwh = []
                bbox_xyxy = outputs[:,:4]
                identities = outputs[:,-1]
                ori_im = draw_boxes(ori_im, bbox_xyxy, identities)

                for bb_xyxy in bbox_xyxy:
                    bbox_tlwh.append(self.deepsort._xyxy_to_tlwh(bb_xyxy))

                results.append((idx_frame-2, bbox_tlwh, identities))

            end = time.time()

            if self.args.display:
                cv2.imshow("test", ori_im)
                cv2.waitKey(1)

            if self.args.save_path:
                self.writer.write(ori_im)
            if self.args.display:
                cv2.imshow("test", ori_im)
                cv2.waitKey(1)
            # save results
            write_results(self.save_results_path, results, 'mot')

            # logging
            self.logger.info("time: {:.03f}s, fps: {:.03f}, detection numbers: {}, tracking numbers: {}" \
                            .format(end-start, 1/(end-start), bbox_xywh.shape[0], len(outputs)))

def parse_args():
    parser = argparse.ArgumentParser()
    parser.add_argument("--config_detection", type=str, default="./configs/rcnn.yaml")
    parser.add_argument("--config_deepsort", type=str, default="./configs/deep_sort.yaml")
    parser.add_argument("--display", action="store_true")
    parser.add_argument("--frame_interval", type=int, default=1)
    parser.add_argument("--display_width", type=int, default=800)
    parser.add_argument("--display_height", type=int, default=600)
    parser.add_argument("--save_path", type=str, default="./outputs/")
    parser.add_argument("--cpu", dest="use_cuda", action="store_false", default=True)
    parser.add_argument("--camera", action="store", dest="cam", type=int, default="-1")
    return parser.parse_args()

if __name__=="__main__":
    os.environ['CUDA_VISIBLE_DEVICES'] = '0'
    args = parse_args()
    cfg = get_config()
    cfg.merge_from_file(args.config_detection)
    cfg.merge_from_file(args.config_deepsort)

    with ImageTracker(cfg, args, r'/media/shenfei/shensdd/deep_sort_new/detector/Pedestron/datasets/zhongxing/testB/Track2/new_img1', 'Track2', 1550, 734) as img_trk:
        img_trk.run()


from fython.unit import *

class FunBol(Unit):
	unit = l.funbol

	def __init__(s, funx):
		s.module = funx.module
		s.lineno = funx.lineno

		s.raw = []
		s.lexem = []

		s.funx = funx
		s.value = funx.value
		s.url_value = s.value
		s.args = []

		s ^ funx

		s.klass_arg = 0
		s.is_coarray_varpec = 0
		s.coarray_ketbol = []

	def __and__(s, other):
		s ^ other

		if s.is_coarray_varpec:
			s.coarray_ketbol.append(other)

		else:
			if other.unit not in [l.commax, l.rparx, l.lpcax]:
				s.args.append(other)

			if other.is_lpcax:
				s.is_coarray_varpec = 1

		return s

	def clone(s, module):
		funx = s.funx.clone(module)
		f = FunBol(funx)

		for a in s.raw[1:]:
			f & a.clone(module)

		return f

	def __str__(s):
		used_arg = []

		b = Buffer()
		b != '{:s}('.format(s.funx)

		if s.klass_arg:
			b != s.klass_arg
			b != ','

		nb_used_arg = 0
		for m in s.args:
			nb_used_arg += 1
			if m.is_opbol:
				if m.modifier[1].value == '=':
					used_arg.append(m.modifier[0].value)
					b != m.modifier[0].value
					for m in m.modifier[1:]:
						b != m
				else:
					b != m
			else:
				b != m

			if not m.is_opx:
				b != ','

		ast = s.ast_target
		if ast:
			if ast.is_routpec:
				arg = ast.argument
				if nb_used_arg < len(arg):
					for a in arg:
						if a not in used_arg:
							guid = s.module.get_guid_tag(a)
							b != '{name:s} = {guid:s},'.format(name=a, guid=guid)

		b.rstrip(',')
		b != ')'

		if s.is_coarray_varpec:
			b != '['
			for m in s.coarray_ketbol:
				b != m
			b.rreplace(',]', ']')

		return str(b)

	@property
	def targetted_ast(s):
		return s.get_ast(s.value)

	@property

pass

	@guid_override.setter
	def guid_override(s, value):
		s.funx.guid_overwrite = value

	@property
	def use_value_as_guid(s):
		s.funx.guid_overwrite = s.value


from fython.unit import *

class FunBol(Unit):
	unit = l.funbol

	def __init__(s, funx):
		s.module = funx.module
		s.lineno = funx.lineno

		s.raw = []
		s.lexem = []

		s.funx = funx
		s.value = funx.value
		s.url_value = s.value
		s.args = []

		s ^ funx

		s.klass_arg = 0
		s.is_coarray_varpec = 0
		s.coarray_ketbol = []

	def __and__(s, other):
		s ^ other

		if s.is_coarray_varpec:
			s.coarray_ketbol.append(other)

		else:
			if other.unit not in [l.commax, l.rparx, l.lpcax]:
				s.args.append(other)

			if other.is_lpcax:
				s.is_coarray_varpec = 1

		return s

	def clone(s, module):
		funx = s.funx.clone(module)
		f = FunBol(funx)

		for a in s.raw[1:]:
			f & a.clone(module)

		return f

	def __str__(s):
		used_arg = []

		b = Buffer()
		b != '{:s}('.format(s.funx)

		if s.klass_arg:
			b != s.klass_arg
			b != ','

		nb_used_arg = 0
		for m in s.args:
			nb_used_arg += 1
			if m.is_opbol:
				if m.modifier[1].value == '=':
					used_arg.append(m.modifier[0].value)
					b != m.modifier[0].value
					for m in m.modifier[1:]:
						b != m
				else:
					b != m
			else:
				b != m

			if not m.is_opx:
				b != ','

		ast = s.ast_target
		if ast:
			if ast.is_routpec:
				arg = ast.argument
				if nb_used_arg < len(arg):
					for a in arg:
						if a not in used_arg:
							guid = s.module.get_guid_tag(a)
							b != '{name:s} = {guid:s},'.format(name=a, guid=guid)

		b.rstrip(',')
		b != ')'

		if s.is_coarray_varpec:
			b != '['
			for m in s.coarray_ketbol:
				b != m
			b.rreplace(',]', ']')

		return str(b)

	@property
	def targetted_ast(s):
		return s.get_ast(s.value)

	@property
	def guid_override(s):
		pass

	@guid_override.setter
	def guid_override(s, value):

	@property
	def use_value_as_guid(s):
		s.funx.guid_overwrite = s.value


from fython.unit import *

class FunBol(Unit):
	unit = l.funbol

	def __init__(s, funx):
		s.module = funx.module
		s.lineno = funx.lineno

		s.raw = []
		s.lexem = []

		s.funx = funx
		s.value = funx.value
		s.url_value = s.value
		s.args = []

		s ^ funx

		s.klass_arg = 0
		s.is_coarray_varpec = 0
		s.coarray_ketbol = []

	def __and__(s, other):
		s ^ other

		if s.is_coarray_varpec:
			s.coarray_ketbol.append(other)

		else:
			if other.unit not in [l.commax, l.rparx, l.lpcax]:
				s.args.append(other)

			if other.is_lpcax:
				s.is_coarray_varpec = 1

		return s

	def clone(s, module):
		funx = s.funx.clone(module)
		f = FunBol(funx)

		for a in s.raw[1:]:
			f & a.clone(module)

		return f

	def __str__(s):
		used_arg = []

		b = Buffer()
		b != '{:s}('.format(s.funx)

		if s.klass_arg:
			b != s.klass_arg
			b != ','

		nb_used_arg = 0
		for m in s.args:
			nb_used_arg += 1
			if m.is_opbol:
				if m.modifier[1].value == '=':
					used_arg.append(m.modifier[0].value)
					b != m.modifier[0].value
					for m in m.modifier[1:]:
						b != m
				else:
					b != m
			else:
				b != m

			if not m.is_opx:
				b != ','

		ast = s.ast_target
		if ast:
			if ast.is_routpec:
				arg = ast.argument
				if nb_used_arg < len(arg):
					for a in arg:
						if a not in used_arg:
							guid = s.module.get_guid_tag(a)
							b != '{name:s} = {guid:s},'.format(name=a, guid=guid)

		b.rstrip(',')
		b != ')'

		if s.is_coarray_varpec:
			b != '['
			for m in s.coarray_ketbol:
				b != m
			b.rreplace(',]', ']')

		return str(b)

	@property
	def targetted_ast(s):
		return s.get_ast(s.value)

	@property
	def guid_override(s):
		pass

	@guid_override.setter
	def guid_override(s, value):
		s.funx.guid_overwrite = value

	@property
	def use_value_as_guid(s):
		s.funx.guid_o


def prediction_layers(
        self,
        features,
        end_points,
        scope="pose",
        reuse=None,
    ):

"""
DeepLabCut2.2 Toolbox (deeplabcut.org)

Please see AUTHORS for contributors.
http://example.com

Adapted from DeeperCut by Eldar Insafutdinov
http://example.com
"""
import re
import tensorflow as tf
import tf_slim as slim
from tf_slim.nets import resnet_v1

from .base import BasePoseNet
from .factory import PoseNetFactory
from .layers import prediction_layer

net_funcs = {
    "resnet_50": resnet_v1.resnet_v1_50,
    "resnet_101": resnet_v1.resnet_v1_101,
    "resnet_152": resnet_v1.resnet_v1_152,
}

@PoseNetFactory.register("resnet")
class PoseResnet(BasePoseNet):
    def __init__(self, cfg):
        super(PoseResnet, self).__init__(cfg)

    def extract_features(self, inputs):
        net_fun = net_funcs[self.cfg['net_type']]
        im_centered = self.center_inputs(inputs)
        with slim.arg_scope(resnet_v1.resnet_arg_scope()):
            net, end_points = net_fun(
                im_centered,
                global_pool=False,
                output_stride=16,
                is_training=False,
            )
        return net, end_points

out = super(PoseResnet, self).prediction_layers(
            features, scope, reuse,
        )
        with tf.compat.v1.variable_scope(scope, reuse=reuse):
            if self.cfg['intermediate_supervision']:
                layer_name = "resnet_v1_{}/block{}/unit_{}/bottleneck_v1"
                num_layers = re.findall("resnet_([0-9]*)", self.cfg['net_type'])[0]
                interm_name = layer_name.format(
                    num_layers, 3, self.cfg['intermediate_supervision_layer']
                )
                block_interm_out = end_points[interm_name]
                out["part_pred_interm"] = prediction_layer(
                    self.cfg,
                    block_interm_out,
                    "intermediate_supervision",
                    self.cfg['num_joints'] + self.cfg.get("num_idchannel", 0),
                )
        return out

    def get_net(self, inputs):
        net, end_points = self.extract_features(inputs)
        return self.prediction_layers(net, end_points)


net_fun = net_funcs[self.cfg['net_type']]
        im_centered = self.center_inputs(inputs)
        with slim.arg_scope(resnet_v1.resnet_arg_scope()):
            net, end_points = net_fun(
                im_centered,
                global_pool=False,
                output_stride=16,
                is_training=False,
            )
        return net, end_points

"""
DeepLabCut2.2 Toolbox (deeplabcut.org)

Please see AUTHORS for contributors.
http://example.com

Adapted from DeeperCut by Eldar Insafutdinov
http://example.com
"""
import re
import tensorflow as tf
import tf_slim as slim
from tf_slim.nets import resnet_v1

from .base import BasePoseNet
from .factory import PoseNetFactory
from .layers import prediction_layer

net_funcs = {
    "resnet_50": resnet_v1.resnet_v1_50,
    "resnet_101": resnet_v1.resnet_v1_101,
    "resnet_152": resnet_v1.resnet_v1_152,
}

@PoseNetFactory.register("resnet")
class PoseResnet(BasePoseNet):
    def __init__(self, cfg):
        super(PoseResnet, self).__init__(cfg)

    def extract_features(self, inputs):

    def prediction_layers(
        self,
        features,
        end_points,
        scope="pose",
        reuse=None,
    ):
        out = super(PoseResnet, self).prediction_layers(
            features, scope, reuse,
        )
        with tf.compat.v1.variable_scope(scope, reuse=reuse):
            if self.cfg['intermediate_supervision']:
                layer_name = "resnet_v1_{}/block{}/unit_{}/bottleneck_v1"
                num_layers = re.findall("resnet_([0-9]*)", self.cfg['net_type'])[0]
                interm_name = layer_name.format(
                    num_layers, 3, self.cfg['intermediate_supervision_layer']
                )
                block_interm_out = end_points[interm_name]
                out["part_pred_interm"] = prediction_layer(
                    self.cfg,
                    block_interm_out,
                    "intermediate_supervision",
                    self.cfg['num_joints'] + self.cfg.get("num_idchannel", 0),
                )
        return out

    def get_net(self, inputs):
        net, end_points = self.extract_features(inputs)
        return self.prediction_layers(net, end_points)


"""
DeepLabCut2.2 Toolbox (deeplabcut.org)

Please see AUTHORS for contributors.
http://example.com

Adapted from DeeperCut by Eldar Insafutdinov
http://example.com
"""
import re
import tensorflow as tf
import tf_slim as slim
from tf_slim.nets import resnet_v1

from .base import BasePoseNet
from .factory import PoseNetFactory
from .layers import prediction_layer

net_funcs = {
    "resnet_50": resnet_v1.resnet_v1_50,
    "resnet_101": resnet_v1.resnet_v1_101,
    "resnet_152": resnet_v1.resnet_v1_152,
}

@PoseNetFactory.register("resnet")
class PoseResnet(BasePoseNet):
    def __init__(self, cfg):
        supe

    def extract_features(self, inputs):
        net_fun = net_funcs[self.cfg['net_type']]
        im_centered = self.center_inputs(inputs)
        with slim.arg_scope(resnet_v1.resnet_arg_scope()):
            net, end_points = net_fun(
                im_centered,
                global_pool=False,
                output_stride=16,
                is_training=False,
            )
        return net, end_points

    def prediction_layers(
        self,
        features,
        end_points,
        scope="pose",
        reuse=None,
    ):
        out = super(PoseResnet, self).prediction_layers(
            features, scope, reuse,
        )
        with tf.compat.v1.variable_scope(scope, reuse=reuse):
            if self.cfg['intermediate_supervision']:
                layer_name = "resnet_v1_{}/block{}/unit_{}/bottleneck_v1"
                num_layers = re.findall("resnet_([0-9]*)", self.cfg['net_type'])[0]
                interm_name = layer_name.format(
                    num_layers, 3, self.cfg['intermediate_supervision_layer']
                )
                block_interm_out = end_points[interm_name]
                out["part_pred_interm"] = prediction_layer(
                    self.cfg,
                    block_interm_out,
                    "intermediate_supervision",
                    self.cfg['num_joints'] + self.cfg.get("num_idchannel", 0),
                )
        return out

    def get_net(self, inputs):
        net, end_points = self.extract_features(inputs)
        return self.prediction_layers(net, end_points)


# pylint: skip-file

"""
Test the external "raw" interface.

"raw" means that types are not converted to pythonic types but are returned as
PureSNMP object instances.
"""

import sys
from datetime import timedelta
from unittest import skipUnless
from unittest.mock import call, patch

import pytest
from x690.types import (
    Integer,
    ObjectIdentifier,
    OctetString,
    Sequence,
    to_bytes,
)

from puresnmp.aio.api.raw import (
    bulkget,
    bulktable,
    bulkwalk,
    get,
    getnext,
    multiget,
    multiset,
    multiwalk,
    set,
    walk,
)
from puresnmp.const import Version
from puresnmp.exc import NoSuchOID, SnmpError
from puresnmp.pdu import BulkGetRequest, GetNextRequest, GetRequest, VarBind
from puresnmp.types import Counter, Gauge, IpAddress, TimeTicks
from puresnmp.util import BulkResult

from . import readbytes, readbytes_multiple
from .asyncmock import AsyncMock

pytestmark = pytest.mark.skipif(
    sys.version_info < (3, 5), reason="requires python3.5"
)

class TestGet:
    @pytest.mark.asyncio
    async def test_get_string(self):
        data = readbytes("get_sysdescr_01.hex")
        expected = OctetString(
            b"Linux d24cf7f36138 4.4.0-28-generic #47-Ubuntu SMP "
            b"Fri Jun 24 10:09:13 UTC 2016 x86_64"
        )
        with patch("puresnmp.aio.api.raw.Transport") as mck:
            mck().send = AsyncMock()
            mck().send.return_value = data
            mck().get_request_id.return_value = 0
            result = await get("::1", "private", "1.2.3")
        assert result == expected

    @pytest.mark.asyncio

data = readbytes("get_sysoid_01.hex")
        expected = ObjectIdentifier.from_string("1.3.6.1.4.1.8072.3.2.10")
        with patch("puresnmp.aio.api.raw.Transport") as mck:
            mck().send = AsyncMock()
            mck().send.return_value = data
            mck().get_request_id.return_value = 0
            result = await get("::1", "private", "1.2.3")
        assert result == expected

    @pytest.mark.asyncio
    async def test_get_multiple_return_binds(self):
        """
        A "GET" response should only return one varbind.
        """
        data = readbytes("get_sysoid_01_error.hex")
        with patch("puresnmp.aio.api.raw.Transport") as mck:
            mck().send = AsyncMock()
            mck().send.return_value = data
            mck().get_request_id.return_value = 0
            with pytest.raises(SnmpError, match="varbind"):
                await get("::1", "private", "1.2.3")

    @pytest.mark.asyncio
    async def test_get_non_existing_oid(self):
        """
        A "GET" response on a non-existing OID should raise an appropriate
        exception.
        """
        data = readbytes("get_non_existing.hex")
        with patch("puresnmp.aio.api.raw.Transport") as mck:
            mck().send = AsyncMock()
            mck().send.return_value = data
            mck().get_request_id.return_value = 0
            with pytest.raises(NoSuchOID):
                await get("::1", "private", "1.2.3")

class TestWalk:
    @pytest.mark.asyncio
    async def test_walk(self):
        response_1 = readbytes("walk_response_1.hex")
        response_2 = readbytes("walk_response_2.hex")
        response_3 = readbytes("walk_response_3.hex")

        expected = [
            VarBind(
                ObjectIdentifier.from_string("1.3.6.1.2.1.2.2.1.5.1"),
                Gauge(10000000),
            ),
            VarBind(
                ObjectIdentifier.from_string("1.3.6.1.2.1.2.2.1.5.13"),
                Gauge(4294967295),
            ),
        ]

        with patch("puresnmp.aio.api.raw.Transport") as mck:
            mck().send = AsyncMock()
            mck().send.side_effect = [response_1, response_2, response_3]
            mck().get_request_id.return_value = 0
            result = []
            async for x in walk("::1", "public", "1.3.6.1.2.1.2.2.1.5"):
                result.append(x)
        assert result == expected

    @pytest.mark.asyncio
    async def test_walk_multiple_return_binds(self):
        """
        A "WALK" response should only return one varbind.
        """
        data = readbytes("get_sysoid_01_error.hex")
        with patch("puresnmp.aio.api.raw.Transport") as mck:
            mck().send = AsyncMock()
            mck().send.return_value = data
            mck().get_request_id.return_value = 0
            with pytest.raises(SnmpError, match="varbind"):
                async for x in walk("::1", "private", "1.2.3"):
                    pass

class TestBulkTable:
    @pytest.mark.asyncio
    async def test_bulktable(self):
        responses = readbytes_multiple("bulktable_response.hex")

        expected = [
            {
                "0": "1",
                "1": Integer(1),
                "2": OctetString(b"lo"),
                "3": Integer(24),
                "4": Integer(65536),
                "5": Gauge(10000000),
                "6": OctetString(b""),
                "7": Integer(1),
                "8": Integer(1),
                "9": TimeTicks(0),
                "10": Counter(172),
                "11": Counter(2),
                "12": Counter(0),
                "13": Counter(0),
                "14": Counter(0),
                "15": Counter(0),
                "16": Counter(172),
                "17": Counter(2),
                "18": Counter(0),
                "19": Counter(0),
                "20": Counter(0),
                "21": Gauge(0),
                "22": ObjectIdentifier(0, 0),
            },
            {
                "0": "4",
                "1": Integer(4),
                "2": OctetString(b"eth0"),
                "3": Integer(6),
                "4": Integer(1500),
                "5": Gauge(4294967295),
                "6": OctetString(b"\x02B\xac\x11\x00\x02"),
                "7": Integer(1),
                "8": Integer(1),
                "9": TimeTicks(0),
                "10": Counter(548760),
                "11": Counter(3888),
                "12": Counter(0),
                "13": Counter(0),
                "14": Counter(0),
                "15": Counter(0),
                "16": Counter(186660),
                "17": Counter(1875),
                "18": Counter(0),
                "19": Counter(0),
                "20": Counter(0),
                "21": Gauge(0),
                "22": ObjectIdentifier(0, 0),
            },
        ]

        with patch("puresnmp.aio.api.raw.Transport") as mck:
            mck().send = AsyncMock()
            mck().send.side_effect = responses
            mck().get_request_id.return_value = 0
            result = []
            table = await bulktable("127.0.0.1", "private", "1.3.6.1.2.1.2.2")
            for row in table:
                result.append(row)
        assert sorted(result, key=lambda x: x["0"]) == expected

class TestMultiGet:
    @pytest.mark.asyncio
    async def test_multiget(self):
        data = readbytes("multiget_response.hex")
        expected = [
            ObjectIdentifier.from_string("1.3.6.1.4.1.8072.3.2.10"),
            OctetString(
                b"Linux 7fbf2f0c363d 4.4.0-28-generic "
                b"#47-Ubuntu SMP Fri Jun 24 10:09:13 "
                b"UTC 2016 x86_64"
            ),
        ]
        with patch("puresnmp.aio.api.raw.Transport") as mck:
            mck().send = AsyncMock()
            mck().get_request_id.return_value = 0
            mck().send.return_value = data
            result = await multiget(
                "::1",
                "private",
                [
                    "1.3.6.1.2.1.1.2.0",
                    "1.3.6.1.2.1.1.1.0",
                ],
            )
        assert result == expected

class TestMultiWalk:

    # TODO (advanced) figure out why this fails on Python 2!
    @skipUnless(
        sys.version_info >= (3, 0),
        "For some reason this fails on Python 2 and I don't know why",
    )
    @pytest.mark.asyncio
    async def test_multi_walk(self):
        response_1 = readbytes("multiwalk_response_1.hex")
        response_2 = readbytes("multiwalk_response_2.hex")
        response_3 = readbytes("multiwalk_response_3.hex")

        expected = [
            VarBind(
                ObjectIdentifier.from_string("1.3.6.1.2.1.2.2.1.1.1"),
                Integer(1),
            ),
            VarBind(
                ObjectIdentifier.from_string("1.3.6.1.2.1.2.2.1.2.1"),
                OctetString(b"lo"),
            ),
            VarBind(
                ObjectIdentifier.from_string("1.3.6.1.2.1.2.2.1.1.78"),
                Integer(78),
            ),
            VarBind(
                ObjectIdentifier.from_string("1.3.6.1.2.1.2.2.1.2.78"),
                OctetString(b"eth0"),
            ),
        ]

        with patch("puresnmp.aio.api.raw.Transport") as mck:
            mck().send = AsyncMock()
            mck().get_request_id.return_value = 0
            mck().send.side_effect = [response_1, response_2, response_3]
            result = []
            async for x in multiwalk(
                "::1", "public", ["1.3.6.1.2.1.2.2.1.1", "1.3.6.1.2.1.2.2.1.2"]
            ):
                result.append(x)
        # TODO (advanced): should order matter in the following result?
        assert len(result) == len(expected)

    @pytest.mark.asyncio
    async def test_eom(self):
        """
        A test for a walk operation which runs into the endOfMibView marker
        """

        data_generator = readbytes_multiple("x690/multiwalk_endofmibview.hex")

        with patch("puresnmp.aio.api.raw.Transport") as mck:
            mck().send = AsyncMock()
            mck().get_request_id.return_value = 0
            mck().send.side_effect = data_generator
            result = []
            async for row in multiwalk(
                "::1",
                "public",
                [
                    "1.3.6.1.6.3.16.1.5.2.1.6.6.95.110.111.110.101.95.1",
                ],
            ):
                result.append(row)

        root = "1.3.6.1.6.3.16.1.5.2.1.6.6.95.110.111.110.101.95.1."
        expected = [
            (root + "0", 1),
            (root + "1", 1),
            (root + "2", 1),
        ]

        simplified_result = [
            (str(oid), value.pythonize()) for oid, value in result
        ]

        assert simplified_result == expected

class TestMultiSet:
    @pytest.mark.asyncio
    async def test_multiset(self):
        """
        Test setting multiple OIDs at once.

        NOTE: The OID '1.3.6.1.2.1.1.5.0' below is manually edited for
              unit-testing. It probably has a different type in the real world!
        """
        data = readbytes("multiset_response.hex")
        with patch("puresnmp.aio.api.raw.Transport") as mck:
            mck().send = AsyncMock()
            mck().get_request_id.return_value = 0
            mck().send.return_value = data
            result = await multiset(
                "::1",
                "private",
                [
                    ("1.3.6.1.2.1.1.4.0", OctetString(b"example@nnthink.com")),
                    ("1.3.6.1.2.1.1.5.0", OctetString(b"hello@world.com")),
                ],
            )
        expected = {
            "1.3.6.1.2.1.1.4.0": OctetString(b"hello@world.com"),
            "1.3.6.1.2.1.1.5.0": OctetString(b"hello@world.com"),
        }
        assert result == expected

class TestGetNext:
    @pytest.mark.asyncio
    async def test_get_call_args(self):
        data = readbytes("dummy.hex")  # any dump would do
        packet = Sequence(
            Integer(Version.V2C),
            OctetString("public"),
            GetNextRequest(0, ObjectIdentifier(1, 2, 3)),
        )
        with patch("puresnmp.aio.api.raw.Transport") as mck:
            mck().send = AsyncMock()
            mck().get_request_id.return_value = 0
            mck().send.return_value = data
            await getnext("::1", "public", "1.2.3")
            mck.assert_called_with(timeout=6)
            mck().send.assert_called_with("::1", 161, to_bytes(packet))

    @pytest.mark.asyncio
    async def test_getnext(self):
        data = readbytes("getnext_response.hex")
        expected = VarBind("1.3.6.1.6.3.1.1.6.1.0", Integer(354522558))

        with patch("puresnmp.aio.api.raw.Transport") as mck:
            mck().send = AsyncMock()
            mck().get_request_id.return_value = 0
            mck().send.return_value = data
            result = await getnext("::1", "private", "1.3.6.1.5")
        assert result == expected

class TestGetBulkGet:
    @pytest.mark.asyncio
    async def test_get_call_args(self):
        data = readbytes("dummy.hex")  # any dump would do
        packet = Sequence(
            Integer(Version.V2C),
            OctetString("public"),
            BulkGetRequest(
                0, 1, 2, ObjectIdentifier(1, 2, 3), ObjectIdentifier(1, 2, 4)
            ),
        )
        with patch("puresnmp.aio.api.raw.Transport") as mck:
            mck().send = AsyncMock()
            mck().get_request_id.return_value = 0
            mck().send.return_value = data
            await bulkget(
                "::1", "public", ["1.2.3"], ["1.2.4"], max_list_size=2
            )
            mck.assert_called_with(timeout=6)
            mck().send.assert_called_with("::1", 161, to_bytes(packet))

    @pytest.mark.asyncio
    async def test_bulkget(self):
        data = readbytes("bulk_get_response.hex")
        expected = BulkResult(
            {
                "1.3.6.1.2.1.1.1.0": OctetString(
                    b"Linux 7e68e60fe303 4.4.0-28-generic "
                    b"#47-Ubuntu SMP Fri Jun 24 10:09:13 UTC 2016 x86_64"
                )
            },
            {
                "1.3.6.1.2.1.3.1.1.1.10.1.172.17.0.1": Integer(10),
                "1.3.6.1.2.1.3.1.1.2.10.1.172.17.0.1": OctetString(
                    b"\x02B\xe2\xc5\x8d\t"
                ),
                "1.3.6.1.2.1.3.1.1.3.10.1.172.17.0.1": IpAddress(
                    b"\xac\x11\x00\x01"
                ),
                "1.3.6.1.2.1.4.1.0": Integer(1),
                "1.3.6.1.2.1.4.3.0": Counter(57),
            },
        )

        with patch("puresnmp.aio.api.raw.Transport") as mck:
            mck().send = AsyncMock()
            mck().get_request_id.return_value = 0
            mck().send.return_value = data
            result = await bulkget(
                "::1",
                "public",
                ["1.3.6.1.2.1.1.1"],
                ["1.3.6.1.2.1.3.1"],
                max_list_size=5,
            )
        assert result == expected

    @pytest.mark.asyncio
    async def test_eom(self):
        """
        Test a bulg-get operation which runs into the "endOfMibView" marker.
        """

        data = readbytes("x690/bulk_get_eom_response.hex")
        with patch("puresnmp.aio.api.raw.Transport") as mck:
            mck().send = AsyncMock()
            mck().get_request_id.return_value = 0
            mck().send.return_value = data
            result = await bulkget(
                "::1", "public", [], ["1.2.4"], max_list_size=10
            )

        expected_scalars = {}
        assert result.scalars == expected_scalars

        root = "1.3.6.1.6.3.16.1.5.2.1.6.6.95.110.111.110.101.95.1."
        expected_listing = {
            root + "0": Integer(1),
            root + "1": Integer(1),
            root + "2": Integer(1),
        }
        assert result.listing == expected_listing

class TestGetBulkWalk:
    @pytest.mark.asyncio
    async def test_get_call_args(self):
        data = readbytes("dummy.hex")  # any dump would do
        packet = Sequence(
            Integer(Version.V2C),
            OctetString("public"),
            BulkGetRequest(0, 0, 2, ObjectIdentifier(1, 2, 3)),
        )
        with patch("puresnmp.aio.api.raw.Transport") as mck:
            mck().send = AsyncMock()
            mck().get_request_id.return_value = 0
            mck().send.return_value = data

            # we need to wrap this in a list to consume the generator.
            async for x in bulkwalk("::1", "public", ["1.2.3"], bulk_size=2):
                pass
            mck.assert_called_with(timeout=6)
            mck().send.assert_called_with("::1", 161, to_bytes(packet))

    @pytest.mark.asyncio
    async def test_get_call_args_issue_22(self):
        data = readbytes("dummy.hex")  # any dump would do
        packet = Sequence(
            Integer(Version.V2C),
            OctetString("public"),
            BulkGetRequest(0, 0, 2, ObjectIdentifier(1, 2, 3)),
        )
        with patch("puresnmp.aio.api.raw.Transport") as mck:
            mck().send = AsyncMock()
            mck().send.return_value = data
            mck().get_request_id.return_value = 0

            with pytest.raises(TypeError, match=r"OIDS.*list"):
                # we need to wrap this in a list to consume the generator.
                async for x in bulkwalk("::1", "public", "1.2.3", bulk_size=2):
                    pass

    @pytest.mark.asyncio
    async def test_bulkwalk(self):
        req1 = readbytes("bulkwalk_request_1.hex")
        req2 = readbytes("bulkwalk_request_2.hex")
        req3 = readbytes("bulkwalk_request_3.hex")

        responses = [
            readbytes("bulkwalk_response_1.hex"),
            readbytes("bulkwalk_response_2.hex"),
            readbytes("bulkwalk_response_3.hex"),
        ]
        with patch("puresnmp.aio.api.raw.Transport") as mck:
            mck().send = AsyncMock()
            mck().send.side_effect = responses

            request_ids = [1001613222, 1001613223, 1001613224]
            mck().get_request_id.side_effect = request_ids

            result = []
            async for x in bulkwalk(
                "127.0.0.1", "private", ["1.3.6.1.2.1.2.2"], bulk_size=20
            ):
                result.append(x)

            mck.assert_called_with(timeout=6)
            assert mck().send.mock_calls == [
                call("127.0.0.1", 161, req1),
                call("127.0.0.1", 161, req2),
                call("127.0.0.1", 161, req3),
            ]

            expected = [
                VarBind("1.3.6.1.2.1.2.2.1.1.1", Integer(1)),
                VarBind("1.3.6.1.2.1.2.2.1.1.10", Integer(10)),
                VarBind("1.3.6.1.2.1.2.2.1.2.1", OctetString(b"lo")),
                VarBind("1.3.6.1.2.1.2.2.1.2.10", OctetString(b"eth0")),
                VarBind("1.3.6.1.2.1.2.2.1.3.1", Integer(24)),
                VarBind("1.3.6.1.2.1.2.2.1.3.10", Integer(6)),
                VarBind("1.3.6.1.2.1.2.2.1.4.1", Integer(65536)),
                VarBind("1.3.6.1.2.1.2.2.1.4.10", Integer(1500)),
                VarBind("1.3.6.1.2.1.2.2.1.5.1", Gauge(10000000)),
                VarBind("1.3.6.1.2.1.2.2.1.5.10", Gauge(4294967295)),
                VarBind("1.3.6.1.2.1.2.2.1.6.1", OctetString(b"")),
                VarBind(
                    "1.3.6.1.2.1.2.2.1.6.10",
                    OctetString(b"\x02\x42\xAC\x11\x00\x02"),
                ),
                VarBind("1.3.6.1.2.1.2.2.1.7.1", Integer(1)),
                VarBind("1.3.6.1.2.1.2.2.1.7.10", Integer(1)),
                VarBind("1.3.6.1.2.1.2.2.1.8.1", Integer(1)),
                VarBind("1.3.6.1.2.1.2.2.1.8.10", Integer(1)),
                VarBind("1.3.6.1.2.1.2.2.1.9.1", TimeTicks(0)),
                VarBind("1.3.6.1.2.1.2.2.1.9.10", TimeTicks(0)),
                VarBind("1.3.6.1.2.1.2.2.1.10.1", Counter(172)),
                VarBind("1.3.6.1.2.1.2.2.1.10.10", Counter(60558)),
                VarBind("1.3.6.1.2.1.2.2.1.11.1", Counter(2)),
                VarBind("1.3.6.1.2.1.2.2.1.11.10", Counter(564)),
                VarBind("1.3.6.1.2.1.2.2.1.12.1", Counter(0)),
                VarBind("1.3.6.1.2.1.2.2.1.12.10", Counter(0)),
                VarBind("1.3.6.1.2.1.2.2.1.13.1", Counter(0)),
                VarBind("1.3.6.1.2.1.2.2.1.13.10", Counter(0)),
                VarBind("1.3.6.1.2.1.2.2.1.14.1", Counter(0)),
                VarBind("1.3.6.1.2.1.2.2.1.14.10", Counter(0)),
                VarBind("1.3.6.1.2.1.2.2.1.15.1", Counter(0)),
                VarBind("1.3.6.1.2.1.2.2.1.15.10", Counter(0)),
                VarBind("1.3.6.1.2.1.2.2.1.16.1", Counter(172)),
                VarBind("1.3.6.1.2.1.2.2.1.16.10", Counter(44295)),
                VarBind("1.3.6.1.2.1.2.2.1.17.1", Counter(2)),
                VarBind("1.3.6.1.2.1.2.2.1.17.10", Counter(442)),
                VarBind("1.3.6.1.2.1.2.2.1.18.1", Counter(0)),
                VarBind("1.3.6.1.2.1.2.2.1.18.10", Counter(0)),
                VarBind("1.3.6.1.2.1.2.2.1.19.1", Counter(0)),
                VarBind("1.3.6.1.2.1.2.2.1.19.10", Counter(0)),
                VarBind("1.3.6.1.2.1.2.2.1.20.1", Counter(0)),
                VarBind("1.3.6.1.2.1.2.2.1.20.10", Counter(0)),
                VarBind("1.3.6.1.2.1.2.2.1.21.1", Gauge(0)),
                VarBind("1.3.6.1.2.1.2.2.1.21.10", Gauge(0)),
                VarBind("1.3.6.1.2.1.2.2.1.22.1", ObjectIdentifier(0, 0)),
                VarBind("1.3.6.1.2.1.2.2.1.22.10", ObjectIdentifier(0, 0)),
            ]
        assert result == expected


"""
        A "GET" response should only return one varbind.
        """
        data = readbytes("get_sysoid_01_error.hex")
        with patch("puresnmp.aio.api.raw.Transport") as mck:
            mck().send = AsyncMock()
            mck().send.return_value = data
            mck().get_request_id.return_value = 0
            with pytest.raises(SnmpError, match="varbind"):
                await get("::1", "private", "1.2.3")

# pylint: skip-file

"""
Test the external "raw" interface.

"raw" means that types are not converted to pythonic types but are returned as
PureSNMP object instances.
"""

import sys
from datetime import timedelta
from unittest import skipUnless
from unittest.mock import call, patch

import pytest
from x690.types import (
    Integer,
    ObjectIdentifier,
    OctetString,
    Sequence,
    to_bytes,
)

from puresnmp.aio.api.raw import (
    bulkget,
    bulktable,
    bulkwalk,
    get,
    getnext,
    multiget,
    multiset,
    multiwalk,
    set,
    walk,
)
from puresnmp.const import Version
from puresnmp.exc import NoSuchOID, SnmpError
from puresnmp.pdu import BulkGetRequest, GetNextRequest, GetRequest, VarBind
from puresnmp.types import Counter, Gauge, IpAddress, TimeTicks
from puresnmp.util import BulkResult

from . import readbytes, readbytes_multiple
from .asyncmock import AsyncMock

pytestmark = pytest.mark.skipif(
    sys.version_info < (3, 5), reason="requires python3.5"
)

class TestGet:
    @pytest.mark.asyncio
    async def test_get_string(self):
        data = readbytes("get_sysdescr_01.hex")
        expected = OctetString(
            b"Linux d24cf7f36138 4.4.0-28-generic #47-Ubuntu SMP "
            b"Fri Jun 24 10:09:13 UTC 2016 x86_64"
        )
        with patch("puresnmp.aio.api.raw.Transport") as mck:
            mck().send = AsyncMock()
            mck().send.return_value = data
            mck().get_request_id.return_value = 0
            result = await get("::1", "private", "1.2.3")
        assert result == expected

    @pytest.mark.asyncio
    async def test_get_oid(self):
        data = readbytes("get_sysoid_01.hex")
        expected = ObjectIdentifier.from_string("1.3.6.1.4.1.8072.3.2.10")
        with patch("puresnmp.aio.api.raw.Transport") as mck:
            mck().send = AsyncMock()
            mck().send.return_value = data
            mck().get_request_id.return_value = 0
            result = await get("::1", "private", "1.2.3")
        assert result == expected

    @pytest.mark.asyncio
    async def test_get_multiple_return_binds(self):

    @pytest.mark.asyncio
    async def test_get_non_existing_oid(self):
        """
        A "GET" response on a non-existing OID should raise an appropriate
        exception.
        """
        data = readbytes("get_non_existing.hex")
        with patch("puresnmp.aio.api.raw.Transport") as mck:
            mck().send = AsyncMock()
            mck().send.return_value = data
            mck().get_request_id.return_value = 0
            with pytest.raises(NoSuchOID):
                await get("::1", "private", "1.2.3")

class TestWalk:
    @pytest.mark.asyncio
    async def test_walk(self):
        response_1 = readbytes("walk_response_1.hex")
        response_2 = readbytes("walk_response_2.hex")
        response_3 = readbytes("walk_response_3.hex")

        expected = [
            VarBind(
                ObjectIdentifier.from_string("1.3.6.1.2.1.2.2.1.5.1"),
                Gauge(10000000),
            ),
            VarBind(
                ObjectIdentifier.from_string("1.3.6.1.2.1.2.2.1.5.13"),
                Gauge(4294967295),
            ),
        ]

        with patch("puresnmp.aio.api.raw.Transport") as mck:
            mck().send = AsyncMock()
            mck().send.side_effect = [response_1, response_2, response_3]
            mck().get_request_id.return_value = 0
            result = []
            async for x in walk("::1", "public", "1.3.6.1.2.1.2.2.1.5"):
                result.append(x)
        assert result == expected

    @pytest.mark.asyncio
    async def test_walk_multiple_return_binds(self):
        """
        A "WALK" response should only return one varbind.
        """
        data = readbytes("get_sysoid_01_error.hex")
        with patch("puresnmp.aio.api.raw.Transport") as mck:
            mck().send = AsyncMock()
            mck().send.return_value = data
            mck().get_request_id.return_value = 0
            with pytest.raises(SnmpError, match="varbind"):
                async for x in walk("::1", "private", "1.2.3"):
                    pass

class TestBulkTable:
    @pytest.mark.asyncio
    async def test_bulktable(self):
        responses = readbytes_multiple("bulktable_response.hex")

        expected = [
            {
                "0": "1",
                "1": Integer(1),
                "2": OctetString(b"lo"),
                "3": Integer(24),
                "4": Integer(65536),
                "5": Gauge(10000000),
                "6": OctetString(b""),
                "7": Integer(1),
                "8": Integer(1),
                "9": TimeTicks(0),
                "10": Counter(172),
                "11": Counter(2),
                "12": Counter(0),
                "13": Counter(0),
                "14": Counter(0),
                "15": Counter(0),
                "16": Counter(172),
                "17": Counter(2),
                "18": Counter(0),
                "19": Counter(0),
                "20": Counter(0),
                "21": Gauge(0),
                "22": ObjectIdentifier(0, 0),
            },
            {
                "0": "4",
                "1": Integer(4),
                "2": OctetString(b"eth0"),
                "3": Integer(6),
                "4": Integer(1500),
                "5": Gauge(4294967295),
                "6": OctetString(b"\x02B\xac\x11\x00\x02"),
                "7": Integer(1),
                "8": Integer(1),
                "9": TimeTicks(0),
                "10": Counter(548760),
                "11": Counter(3888),
                "12": Counter(0),
                "13": Counter(0),
                "14": Counter(0),
                "15": Counter(0),
                "16": Counter(186660),
                "17": Counter(1875),
                "18": Counter(0),
                "19": Counter(0),
                "20": Counter(0),
                "21": Gauge(0),
                "22": ObjectIdentifier(0, 0),
            },
        ]

        with patch("puresnmp.aio.api.raw.Transport") as mck:
            mck().send = AsyncMock()
            mck().send.side_effect = responses
            mck().get_request_id.return_value = 0
            result = []
            table = await bulktable("127.0.0.1", "private", "1.3.6.1.2.1.2.2")
            for row in table:
                result.append(row)
        assert sorted(result, key=lambda x: x["0"]) == expected

class TestMultiGet:
    @pytest.mark.asyncio
    async def test_multiget(self):
        data = readbytes("multiget_response.hex")
        expected = [
            ObjectIdentifier.from_string("1.3.6.1.4.1.8072.3.2.10"),
            OctetString(
                b"Linux 7fbf2f0c363d 4.4.0-28-generic "
                b"#47-Ubuntu SMP Fri Jun 24 10:09:13 "
                b"UTC 2016 x86_64"
            ),
        ]
        with patch("puresnmp.aio.api.raw.Transport") as mck:
            mck().send = AsyncMock()
            mck().get_request_id.return_value = 0
            mck().send.return_value = data
            result = await multiget(
                "::1",
                "private",
                [
                    "1.3.6.1.2.1.1.2.0",
                    "1.3.6.1.2.1.1.1.0",
                ],
            )
        assert result == expected

class TestMultiWalk:

    # TODO (advanced) figure out why this fails on Python 2!
    @skipUnless(
        sys.version_info >= (3, 0),
        "For some reason this fails on Python 2 and I don't know why",
    )
    @pytest.mark.asyncio
    async def test_multi_walk(self):
        response_1 = readbytes("multiwalk_response_1.hex")
        response_2 = readbytes("multiwalk_response_2.hex")
        response_3 = readbytes("multiwalk_response_3.hex")

        expected = [
            VarBind(
                ObjectIdentifier.from_string("1.3.6.1.2.1.2.2.1.1.1"),
                Integer(1),
            ),
            VarBind(
                ObjectIdentifier.from_string("1.3.6.1.2.1.2.2.1.2.1"),
                OctetString(b"lo"),
            ),
            VarBind(
                ObjectIdentifier.from_string("1.3.6.1.2.1.2.2.1.1.78"),
                Integer(78),
            ),
            VarBind(
                ObjectIdentifier.from_string("1.3.6.1.2.1.2.2.1.2.78"),
                OctetString(b"eth0"),
            ),
        ]

        with patch("puresnmp.aio.api.raw.Transport") as mck:
            mck().send = AsyncMock()
            mck().get_request_id.return_value = 0
            mck().send.side_effect = [response_1, response_2, response_3]
            result = []
            async for x in multiwalk(
                "::1", "public", ["1.3.6.1.2.1.2.2.1.1", "1.3.6.1.2.1.2.2.1.2"]
            ):
                result.append(x)
        # TODO (advanced): should order matter in the following result?
        assert len(result) == len(expected)

    @pytest.mark.asyncio
    async def test_eom(self):
        """
        A test for a walk operation which runs into the endOfMibView marker
        """

        data_generator = readbytes_multiple("x690/multiwalk_endofmibview.hex")

        with patch("puresnmp.aio.api.raw.Transport") as mck:
            mck().send = AsyncMock()
            mck().get_request_id.return_value = 0
            mck().send.side_effect = data_generator
            result = []
            async for row in multiwalk(
                "::1",
                "public",
                [
                    "1.3.6.1.6.3.16.1.5.2.1.6.6.95.110.111.110.101.95.1",
                ],
            ):
                result.append(row)

        root = "1.3.6.1.6.3.16.1.5.2.1.6.6.95.110.111.110.101.95.1."
        expected = [
            (root + "0", 1),
            (root + "1", 1),
            (root + "2", 1),
        ]

        simplified_result = [
            (str(oid), value.pythonize()) for oid, value in result
        ]

        assert simplified_result == expected

class TestMultiSet:
    @pytest.mark.asyncio
    async def test_multiset(self):
        """
        Test setting multiple OIDs at once.

        NOTE: The OID '1.3.6.1.2.1.1.5.0' below is manually edited for
              unit-testing. It probably has a different type in the real world!
        """
        data = readbytes("multiset_response.hex")
        with patch("puresnmp.aio.api.raw.Transport") as mck:
            mck().send = AsyncMock()
            mck().get_request_id.return_value = 0
            mck().send.return_value = data
            result = await multiset(
                "::1",
                "private",
                [
                    ("1.3.6.1.2.1.1.4.0", OctetString(b"example@nnthink.com")),
                    ("1.3.6.1.2.1.1.5.0", OctetString(b"hello@world.com")),
                ],
            )
        expected = {
            "1.3.6.1.2.1.1.4.0": OctetString(b"hello@world.com"),
            "1.3.6.1.2.1.1.5.0": OctetString(b"hello@world.com"),
        }
        assert result == expected

class TestGetNext:
    @pytest.mark.asyncio
    async def test_get_call_args(self):
        data = readbytes("dummy.hex")  # any dump would do
        packet = Sequence(
            Integer(Version.V2C),
            OctetString("public"),
            GetNextRequest(0, ObjectIdentifier(1, 2, 3)),
        )
        with patch("puresnmp.aio.api.raw.Transport") as mck:
            mck().send = AsyncMock()
            mck().get_request_id.return_value = 0
            mck().send.return_value = data
            await getnext("::1", "public", "1.2.3")
            mck.assert_called_with(timeout=6)
            mck().send.assert_called_with("::1", 161, to_bytes(packet))

    @pytest.mark.asyncio
    async def test_getnext(self):
        data = readbytes("getnext_response.hex")
        expected = VarBind("1.3.6.1.6.3.1.1.6.1.0", Integer(354522558))

        with patch("puresnmp.aio.api.raw.Transport") as mck:
            mck().send = AsyncMock()
            mck().get_request_id.return_value = 0
            mck().send.return_value = data
            result = await getnext("::1", "private", "1.3.6.1.5")
        assert result == expected

class TestGetBulkGet:
    @pytest.mark.asyncio
    async def test_get_call_args(self):
        data = readbytes("dummy.hex")  # any dump would do
        packet = Sequence(
            Integer(Version.V2C),
            OctetString("public"),
            BulkGetRequest(
                0, 1, 2, ObjectIdentifier(1, 2, 3), ObjectIdentifier(1, 2, 4)
            ),
        )
        with patch("puresnmp.aio.api.raw.Transport") as mck:
            mck().send = AsyncMock()
            mck().get_request_id.return_value = 0
            mck().send.return_value = data
            await bulkget(
                "::1", "public", ["1.2.3"], ["1.2.4"], max_list_size=2
            )
            mck.assert_called_with(timeout=6)
            mck().send.assert_called_with("::1", 161, to_bytes(packet))

    @pytest.mark.asyncio
    async def test_bulkget(self):
        data = readbytes("bulk_get_response.hex")
        expected = BulkResult(
            {
                "1.3.6.1.2.1.1.1.0": OctetString(
                    b"Linux 7e68e60fe303 4.4.0-28-generic "
                    b"#47-Ubuntu SMP Fri Jun 24 10:09:13 UTC 2016 x86_64"
                )
            },
            {
                "1.3.6.1.2.1.3.1.1.1.10.1.172.17.0.1": Integer(10),
                "1.3.6.1.2.1.3.1.1.2.10.1.172.17.0.1": OctetString(
                    b"\x02B\xe2\xc5\x8d\t"
                ),
                "1.3.6.1.2.1.3.1.1.3.10.1.172.17.0.1": IpAddress(
                    b"\xac\x11\x00\x01"
                ),
                "1.3.6.1.2.1.4.1.0": Integer(1),
                "1.3.6.1.2.1.4.3.0": Counter(57),
            },
        )

        with patch("puresnmp.aio.api.raw.Transport") as mck:
            mck().send = AsyncMock()
            mck().get_request_id.return_value = 0
            mck().send.return_value = data
            result = await bulkget(
                "::1",
                "public",
                ["1.3.6.1.2.1.1.1"],
                ["1.3.6.1.2.1.3.1"],
                max_list_size=5,
            )
        assert result == expected

    @pytest.mark.asyncio
    async def test_eom(self):
        """
        Test a bulg-get operation which runs into the "endOfMibView" marker.
        """

        data = readbytes("x690/bulk_get_eom_response.hex")
        with patch("puresnmp.aio.api.raw.Transport") as mck:
            mck().send = AsyncMock()
            mck().get_request_id.return_value = 0
            mck().send.return_value = data
            result = await bulkget(
                "::1", "public", [], ["1.2.4"], max_list_size=10
            )

        expected_scalars = {}
        assert result.scalars == expected_scalars

        root = "1.3.6.1.6.3.16.1.5.2.1.6.6.95.110.111.110.101.95.1."
        expected_listing = {
            root + "0": Integer(1),
            root + "1": Integer(1),
            root + "2": Integer(1),
        }
        assert result.listing == expected_listing

class TestGetBulkWalk:
    @pytest.mark.asyncio
    async def test_get_call_args(self):
        data = readbytes("dummy.hex")  # any dump would do
        packet = Sequence(
            Integer(Version.V2C),
            OctetString("public"),
            BulkGetRequest(0, 0, 2, ObjectIdentifier(1, 2, 3)),
        )
        with patch("puresnmp.aio.api.raw.Transport") as mck:
            mck().send = AsyncMock()
            mck().get_request_id.return_value = 0
            mck().send.return_value = data

            # we need to wrap this in a list to consume the generator.
            async for x in bulkwalk("::1", "public", ["1.2.3"], bulk_size=2):
                pass
            mck.assert_called_with(timeout=6)
            mck().send.assert_called_with("::1", 161, to_bytes(packet))

    @pytest.mark.asyncio
    async def test_get_call_args_issue_22(self):
        data = readbytes("dummy.hex")  # any dump would do
        packet = Sequence(
            Integer(Version.V2C),
            OctetString("public"),
            BulkGetRequest(0, 0, 2, ObjectIdentifier(1, 2, 3)),
        )
        with patch("puresnmp.aio.api.raw.Transport") as mck:
            mck().send = AsyncMock()
            mck().send.return_value = data
            mck().get_request_id.return_value = 0

            with pytest.raises(TypeError, match=r"OIDS.*list"):
                # we need to wrap this in a list to consume the generator.
                async for x in bulkwalk("::1", "public", "1.2.3", bulk_size=2):
                    pass

    @pytest.mark.asyncio
    async def test_bulkwalk(self):
        req1 = readbytes("bulkwalk_request_1.hex")
        req2 = readbytes("bulkwalk_request_2.hex")
        req3 = readbytes("bulkwalk_request_3.hex")

        responses = [
            readbytes("bulkwalk_response_1.hex"),
            readbytes("bulkwalk_response_2.hex"),
            readbytes("bulkwalk_response_3.hex"),
        ]
        with patch("puresnmp.aio.api.raw.Transport") as mck:
            mck().send = AsyncMock()
            mck().send.side_effect = responses

            request_ids = [1001613222, 1001613223, 1001613224]
            mck().get_request_id.side_effect = request_ids

            result = []
            async for x in bulkwalk(
                "127.0.0.1", "private", ["1.3.6.1.2.1.2.2"], bulk_size=20
            ):
                result.append(x)

            mck.assert_called_with(timeout=6)
            assert mck().send.mock_calls == [
                call("127.0.0.1", 161, req1),
                call("127.0.0.1", 161, req2),
                call("127.0.0.1", 161, req3),
            ]

            expected = [
                VarBind("1.3.6.1.2.1.2.2.1.1.1", Integer(1)),
                VarBind("1.3.6.1.2.1.2.2.1.1.10", Integer(10)),
                VarBind("1.3.6.1.2.1.2.2.1.2.1", OctetString(b"lo")),
                VarBind("1.3.6.1.2.1.2.2.1.2.10", OctetString(b"eth0")),
                VarBind("1.3.6.1.2.1.2.2.1.3.1", Integer(24)),
                VarBind("1.3.6.1.2.1.2.2.1.3.10", Integer(6)),
                VarBind("1.3.6.1.2.1.2.2.1.4.1", Integer(65536)),
                VarBind("1.3.6.1.2.1.2.2.1.4.10", Integer(1500)),
                VarBind("1.3.6.1.2.1.2.2.1.5.1", Gauge(10000000)),
                VarBind("1.3.6.1.2.1.2.2.1.5.10", Gauge(4294967295)),
                VarBind("1.3.6.1.2.1.2.2.1.6.1", OctetString(b"")),
                VarBind(
                    "1.3.6.1.2.1.2.2.1.6.10",
                    OctetString(b"\x02\x42\xAC\x11\x00\x02"),
                ),
                VarBind("1.3.6.1.2.1.2.2.1.7.1", Integer(1)),
                VarBind("1.3.6.1.2.1.2.2.1.7.10", Integer(1)),
                VarBind("1.3.6.1.2.1.2.2.1.8.1", Integer(1)),
                VarBind("1.3.6.1.2.1.2.2.1.8.10", Integer(1)),
                VarBind("1.3.6.1.2.1.2.2.1.9.1", TimeTicks(0)),
                VarBind("1.3.6.1.2.1.2.2.1.9.10", TimeTicks(0)),
                VarBind("1.3.6.1.2.1.2.2.1.10.1", Counter(172)),
                VarBind("1.3.6.1.2.1.2.2.1.10.10", Counter(60558)),
                VarBind("1.3.6.1.2.1.2.2.1.11.1", Counter(2)),
                VarBind("1.3.6.1.2.1.2.2.1.11.10", Counter(564)),
                VarBind("1.3.6.1.2.1.2.2.1.12.1", Counter(0)),
                VarBind("1.3.6.1.2.1.2.2.1.12.10", Counter(0)),
                VarBind("1.3.6.1.2.1.2.2.1.13.1", Counter(0)),
                VarBind("1.3.6.1.2.1.2.2.1.13.10", Counter(0)),
                VarBind("1.3.6.1.2.1.2.2.1.14.1", Counter(0)),
                VarBind("1.3.6.1.2.1.2.2.1.14.10", Counter(0)),
                VarBind("1.3.6.1.2.1.2.2.1.15.1", Counter(0)),
                VarBind("1.3.6.1.2.1.2.2.1.15.10", Counter(0)),
                VarBind("1.3.6.1.2.1.2.2.1.16.1", Counter(172)),
                VarBind("1.3.6.1.2.1.2.2.1.16.10", Counter(44295)),
                VarBind("1.3.6.1.2.1.2.2.1.17.1", Counter(2)),
                VarBind("1.3.6.1.2.1.2.2.1.17.10", Counter(442)),
                VarBind("1.3.6.1.2.1.2.2.1.18.1", Counter(0)),
                VarBind("1.3.6.1.2.1.2.2.1.18.10", Counter(0)),
                VarBind("1.3.6.1.2.1.2.2.1.19.1", Counter(0)),
                VarBind("1.3.6.1.2.1.2.2.1.19.10", Counter(0)),
                VarBind("1.3.6.1.2.1.2.2.1.20.1", Counter(0)),
                VarBind("1.3.6.1.2.1.2.2.1.20.10", Counter(0)),
                VarBind("1.3.6.1.2.1.2.2.1.21.1", Gauge(0)),
                VarBind("1.3.6.1.2.1.2.2.1.21.10", Gauge(0)),
                VarBind("1.3.6.1.2.1.2.2.1.22.1", ObjectIdentifier(0, 0)),
                VarBind("1.3.6.1.2.1.2.2.1.22.10", ObjectIdentifier(0, 0)),
            ]
        assert result == expected