def Pack(self, msg, type_url_prefix='type.googleapis.com/',
           deterministic=None):
    """Packs the specified message into current Any message."""
    if len(type_url_prefix) < 1 or type_url_prefix[-1] != '/':
      self.type_url = '%s/%s' % (type_url_prefix, msg.DESCRIPTOR.full_name)
    else:
      self.type_url = '%s%s' % (type_url_prefix, msg.DESCRIPTOR.full_name)
    self.value = msg.SerializeToString(deterministic=deterministic)


def _path_get(self, data, path):
        """Return the nested data at the given path.

        For instance:
            data = {'foo': ['bar', 'baz']}
            path = ['foo', 0]
            ==> 'bar'
        """
        # jmespath isn't used here because it would be difficult to actually
        # create the jmespath query when taking all of the unknowns of key
        # structure into account. Gross though this is, it is simple and not
        # very error prone.
        d = data
        for step in path:
            d = d[step]
        return d


def create_client(
        self,
        service_name,
        region_name=None,
        api_version=None,
        use_ssl=True,
        verify=None,
        endpoint_url=None,
        aws_access_key_id=None,
        aws_secret_access_key=None,
        aws_session_token=None,
        config=None,
    ):
        """Create a botocore client.

        :type service_name: string
        :param service_name: The name of the service for which a client will
            be created.  You can use the ``Session.get_available_services()``
            method to get a list of all available service names.

        :type region_name: string
        :param region_name: The name of the region associated with the client.
            A client is associated with a single region.

        :type api_version: string
        :param api_version: The API version to use.  By default, botocore will
            use the latest API version when creating a client.  You only need
            to specify this parameter if you want to use a previous API version
            of the client.

        :type use_ssl: boolean
        :param use_ssl: Whether or not to use SSL.  By default, SSL is used.
            Note that not all services support non-ssl connections.

        :type verify: boolean/string
        :param verify: Whether or not to verify SSL certificates.
            By default SSL certificates are verified.  You can provide the
            following values:

            * False - do not validate SSL certificates.  SSL will still be
              used (unless use_ssl is False), but SSL certificates
              will not be verified.
            * path/to/cert/bundle.pem - A filename of the CA cert bundle to
              uses.  You can specify this argument if you want to use a
              different CA cert bundle than the one used by botocore.

        :type endpoint_url: string
        :param endpoint_url: The complete URL to use for the constructed
            client.  Normally, botocore will automatically construct the
            appropriate URL to use when communicating with a service.  You can
            specify a complete URL (including the "http/https" scheme) to
            override this behavior.  If this value is provided, then
            ``use_ssl`` is ignored.

        :type aws_access_key_id: string
        :param aws_access_key_id: The access key to use when creating
            the client.  This is entirely optional, and if not provided,
            the credentials configured for the session will automatically
            be used.  You only need to provide this argument if you want
            to override the credentials used for this specific client.

        :type aws_secret_access_key: string
        :param aws_secret_access_key: The secret key to use when creating
            the client.  Same semantics as aws_access_key_id above.

        :type aws_session_token: string
        :param aws_session_token: The session token to use when creating
            the client.  Same semantics as aws_access_key_id above.

        :type config: botocore.client.Config
        :param config: Advanced client configuration options. If a value
            is specified in the client config, its value will take precedence
            over environment variables and configuration values, but not over
            a value passed explicitly to the method. If a default config
            object is set on the session, the config object used when creating
            the client will be the result of calling ``merge()`` on the
            default config with the config provided to this call.

        :rtype: botocore.client.BaseClient
        :return: A botocore client instance

        """
        default_client_config = self.get_default_client_config()
        # If a config is provided and a default config is set, then
        # use the config resulting from merging the two.
        if config is not None and default_client_config is not None:
            config = default_client_config.merge(config)
        # If a config was not provided then use the default
        # client config from the session
        elif default_client_config is not None:
            config = default_client_config

        region_name = self._resolve_region_name(region_name, config)

        # Figure out the verify value base on the various
        # configuration options.
        if verify is None:
            verify = self.get_config_variable('ca_bundle')

        if api_version is None:
            api_version = self.get_config_variable('api_versions').get(
                service_name, None
            )

        loader = self.get_component('data_loader')
        event_emitter = self.get_component('event_emitter')
        response_parser_factory = self.get_component('response_parser_factory')
        if config is not None and config.signature_version is UNSIGNED:
            credentials = None
        elif (
            aws_access_key_id is not None and aws_secret_access_key is not None
        ):
            credentials = botocore.credentials.Credentials(
                access_key=aws_access_key_id,
                secret_key=aws_secret_access_key,
                token=aws_session_token,
            )
        elif self._missing_cred_vars(aws_access_key_id, aws_secret_access_key):
            raise PartialCredentialsError(
                provider='explicit',
                cred_var=self._missing_cred_vars(
                    aws_access_key_id, aws_secret_access_key
                ),
            )
        else:
            credentials = self.get_credentials()
        auth_token = self.get_auth_token()
        endpoint_resolver = self._get_internal_component('endpoint_resolver')
        exceptions_factory = self._get_internal_component('exceptions_factory')
        config_store = self.get_component('config_store')
        defaults_mode = self._resolve_defaults_mode(config, config_store)
        if defaults_mode != 'legacy':
            smart_defaults_factory = self._get_internal_component(
                'smart_defaults_factory'
            )
            config_store = copy.deepcopy(config_store)
            smart_defaults_factory.merge_smart_defaults(
                config_store, defaults_mode, region_name
            )
        client_creator = botocore.client.ClientCreator(
            loader,
            endpoint_resolver,
            self.user_agent(),
            event_emitter,
            retryhandler,
            translate,
            response_parser_factory,
            exceptions_factory,
            config_store,
        )
        client = client_creator.create_client(
            service_name=service_name,
            region_name=region_name,
            is_secure=use_ssl,
            endpoint_url=endpoint_url,
            verify=verify,
            credentials=credentials,
            scoped_config=self.get_scoped_config(),
            client_config=config,
            api_version=api_version,
            auth_token=auth_token,
        )
        monitor = self._get_internal_component('monitor')
        if monitor is not None:
            monitor.register(client.meta.events)
        return client


def __init__(self, num_classes, in_channels=3, depth=5,
                 start_filts=64, up_mode='transpose', same_channels=False,
                 merge_mode='concat', **kwargs):
        """
        Arguments:
            in_channels: int, number of channels in the input tensor.
                Default is 3 for RGB images.
            depth: int, number of MaxPools in the U-Net.
            start_filts: int, number of convolutional filters for the
                first conv.
            up_mode: string, type of upconvolution. Choices: 'transpose'
                for transpose convolution or 'upsample' for nearest neighbour
                upsampling.
        """
        super(UNet, self).__init__()

        if up_mode in ('transpose', 'upsample'):
            self.up_mode = up_mode
        else:
            raise ValueError("\"{}\" is not a valid mode for "
                             "upsampling. Only \"transpose\" and "
                             "\"upsample\" are allowed.".format(up_mode))

        if merge_mode in ('concat', 'add'):
            self.merge_mode = merge_mode
        else:
            raise ValueError("\"{}\" is not a valid mode for"
                             "merging up and down paths. "
                             "Only \"concat\" and "
                             "\"add\" are allowed.".format(up_mode))

        # NOTE: up_mode 'upsample' is incompatible with merge_mode 'add'
        if self.up_mode == 'upsample' and self.merge_mode == 'add':
            raise ValueError("up_mode \"upsample\" is incompatible "
                             "with merge_mode \"add\" at the moment "
                             "because it doesn't make sense to use "
                             "nearest neighbour to reduce "
                             "depth channels (by half).")

        self.num_classes = num_classes
        self.in_channels = in_channels
        self.start_filts = start_filts
        self.depth = depth

        self.down_convs = []
        self.up_convs = []

        # create the encoder pathway and add to a list
        for i in range(depth):
            ins = self.in_channels if i == 0 else outs
            outs = self.start_filts*(2**i) if not same_channels else self.in_channels
            pooling = True if i < depth-1 else False
            #print("down ins, outs: ", ins, outs)  # [latent dim, 32], [32, 64]...[128, 256]

            down_conv = DownConv(ins, outs, pooling=pooling)
            self.down_convs.append(down_conv)

        # create the decoder pathway and add to a list
        # - careful! decoding only requires depth-1 blocks
        for i in range(depth-1):
            ins = outs
            outs = ins // 2 if not same_channels else ins
            up_conv = UpConv(ins, outs, up_mode=up_mode,
                merge_mode=merge_mode)
            self.up_convs.append(up_conv)
            #print("up ins, outs: ", ins, outs)# [256, 128]...[64, 32]; final 32 to latent is done through self.conv_final

        # add the list of modules to current module
        self.down_convs = nn.ModuleList(self.down_convs)
        self.up_convs = nn.ModuleList(self.up_convs)

        self.conv_final = conv1x1(outs, self.num_classes)

        self.reset_params()


def marginal_lambda(self, t):
        """
        Compute lambda_t = log(alpha_t) - log(sigma_t) of a given continuous-time label t in [0, T].
        """
        log_mean_coeff = self.marginal_log_mean_coeff(t)
        log_std = 0.5 * torch.log(1. - torch.exp(2. * log_mean_coeff))
        return log_mean_coeff - log_std


def build_fno(self, num_fno_modes: List[int]) -> None:
        """construct FNO block.
        Parameters
        ----------
        num_fno_modes : List[int]
            Number of Fourier modes kept in spectral convolutions

        """
        # Build Neural Fourier Operators
        self.spconv_layers = nn.ModuleList()
        self.conv_layers = nn.ModuleList()
        for _ in range(self.num_fno_layers):
            self.spconv_layers.append(
                layers.SpectralConv3d(
                    self.fno_width,
                    self.fno_width,
                    num_fno_modes[0],
                    num_fno_modes[1],
                    num_fno_modes[2],
                )
            )
            self.conv_layers.append(nn.Conv3d(self.fno_width, self.fno_width, 1))


def is_ignored(path, working_path, ignore_patterns):
    """
    Check if the path needs to be ignored
    """
    # Get the git root path to stop the search
    git_root_path = Path(__file__) / Path(working_path)
    git_root_path = git_root_path.resolve()

    for pattern in ignore_patterns:
        normalized_pattern = pattern.rstrip("/")

        # Filter paths that are outside git root
        relevant_children = [
            part
            for part in [path] + list(path.parents)
            if git_root_path in part.parents or part == git_root_path
        ]

        # Check the directory itself and each parent directory
        for part in relevant_children:
            # Match directories (patterns ending with '/')
            if pattern.endswith("/") and part.is_dir():
                if fnmatch.fnmatch(part.name, normalized_pattern):
                    return True

            # Match files or directories without a trailing '/'
            if not pattern.endswith("/") and (
                fnmatch.fnmatch(str(part), pattern)
                or fnmatch.fnmatch(part.name, normalized_pattern)
            ):
                return True

    return False


@check_ort_version()
@pytest.mark.parametrize("dft_dim", [-1, 1])
def test_irfft_ort_op(
    test_data: Tensor, norm: str, dft_dim: int, rtol: float = 1e-5, atol: float = 1e-5
):
    """Test IRFFT onnx runtime operation is consistent with torch irfft"""
    x = test_data.transpose(-1, dft_dim)
    x = fft.rfft(x, dim=dft_dim, norm=norm)

    class CustomIrfft(nn.Module):
        def forward(self, y):
            return fft.irfft(y, dim=dft_dim, norm=norm)

    model = CustomIrfft()
    output = model(x)

    x0 = torch.view_as_real(x)
    onnx_model = export_to_onnx_stream(model, x0)
    output_ort = run_onnx_inference(onnx_model, (x0,))
    assert len(output_ort) == 1
    output_onnx = torch.Tensor(output_ort[0])

    assert torch.allclose(output, output_onnx, rtol, atol)


def build_sensor_observation_space(self) -> gymnasium.spaces.Dict:
        """Build observation space for all sensor types.

        Returns:
            gymnasium.spaces.Dict: The observation space generated by sensors bound with agent.
        """
        obs_space_dict = {}

        for sensor in self.sensor_conf.sensors:  # Explicitly listed sensors
            dim = self.sensor_info.sensor_dim[sensor]
            obs_space_dict[sensor] = gymnasium.spaces.Box(-np.inf, np.inf, (dim,), dtype=np.float64)
        # Velocities don't have wraparound effects that rotational positions do
        # Wraparounds are not kind to neural networks
        # Whereas the angle 2*pi is very close to 0, this isn't true in the network
        # In theory the network could learn this, but in practice we simplify it
        # when the sensors_angle_components switch is enabled.
        for sensor in self.sensor_info.hinge_vel_names:
            obs_space_dict[sensor] = gymnasium.spaces.Box(-np.inf, np.inf, (1,), dtype=np.float64)
        for sensor in self.sensor_info.ballangvel_names:
            obs_space_dict[sensor] = gymnasium.spaces.Box(-np.inf, np.inf, (3,), dtype=np.float64)
        if self.sensor_info.freejoint_pos_name:
            sensor = self.sensor_info.freejoint_pos_name
            obs_space_dict[sensor] = gymnasium.spaces.Box(-np.inf, np.inf, (1,), dtype=np.float64)
            obs_space_dict[sensor + '1'] = gymnasium.spaces.Box(
                -np.inf,
                np.inf,
                (1,),
                dtype=np.float64,
            )
        if self.sensor_info.freejoint_qvel_name:
            sensor = self.sensor_info.freejoint_qvel_name
            obs_space_dict[sensor] = gymnasium.spaces.Box(-np.inf, np.inf, (3,), dtype=np.float64)
            obs_space_dict[sensor + '1'] = gymnasium.spaces.Box(
                -np.inf,
                np.inf,
                (3,),
                dtype=np.float64,
            )
        # Angular positions have wraparound effects, so output something more friendly
        if self.sensor_conf.sensors_angle_components:
            # Single joints are turned into sin(x), cos(x) pairs
            # These should be easier to learn for neural networks,
            # Since for angles, small perturbations in angle give small differences in sin/cos
            for sensor in self.sensor_info.hinge_pos_names:
                obs_space_dict[sensor] = gymnasium.spaces.Box(
                    -np.inf,
                    np.inf,
                    (2,),
                    dtype=np.float64,
                )
            # Quaternions are turned into 3x3 rotation matrices
            # Quaternions have a wraparound issue in how they are normalized,
            # where the convention is to change the sign so the first element to be positive.
            # If the first element is close to 0, this can mean small differences in rotation
            # lead to large differences in value as the latter elements change sign.
            # This also means that the first element of the quaternion is not expectation zero.
            # The SO(3) rotation representation would be a good replacement here,
            # since it smoothly varies between values in all directions (the property we want),
            # but right now we have very little code to support SO(3) rotations.
            # Instead we use a 3x3 rotation matrix, which if normalized, smoothly varies as well.
            for sensor in self.sensor_info.ballquat_names:
                obs_space_dict[sensor] = gymnasium.spaces.Box(
                    -np.inf,
                    np.inf,
                    (3, 3),
                    dtype=np.float64,
                )
        else:
            # Otherwise include the sensor without any processing
            for sensor in self.sensor_info.hinge_pos_names:
                obs_space_dict[sensor] = gymnasium.spaces.Box(
                    -np.inf,
                    np.inf,
                    (1,),
                    dtype=np.float64,
                )
            for sensor in self.sensor_info.ballquat_names:
                obs_space_dict[sensor] = gymnasium.spaces.Box(
                    -np.inf,
                    np.inf,
                    (4,),
                    dtype=np.float64,
                )

        return obs_space_dict


def update_ema(target_params, source_params, rate=0.99):
    """
    Update target parameters to be closer to those of source parameters using
    an exponential moving average.

    :param target_params: the target parameter sequence.
    :param source_params: the source parameter sequence.
    :param rate: the EMA rate (closer to 1 means slower).
    """
    for targ, src in zip(target_params, source_params):
        targ.detach().mul_(rate).add_(src, alpha=1 - rate)


def forward(self, query_feats, key_feats):
        """Forward function."""
        context = super(ObjectAttentionBlock,
                        self).forward(query_feats, key_feats)
        output = self.bottleneck(torch.cat([context, query_feats], dim=1))
        if self.query_downsample is not None:
            output = resize(query_feats)

        return output


def load_data(
        self,
        state: Optional[IssueState] = IssueState.OPEN,
        labelFilters: Optional[List[Tuple[str, FilterType]]] = None,
    ) -> List[Document]:
        """
        Load issues from a repository and converts them to documents.

        Each issue is converted to a document by doing the following:

        - The text of the document is the concatenation of the title and the body of the issue.
        - The title of the document is the title of the issue.
        - The doc_id of the document is the issue number.
        - The extra_info of the document is a dictionary with the following keys:
            - state: State of the issue.
            - created_at: Date when the issue was created.
            - closed_at: Date when the issue was closed. Only present if the issue is closed.
            - url: URL of the issue.
            - assignee: Login of the user assigned to the issue. Only present if the issue is assigned.
        - The embedding of the document is None.
        - The doc_hash of the document is None.

        Args:
            - state (IssueState): State of the issues to retrieve. Default is IssueState.OPEN.
            - labelFilters: an optional list of filters to apply to the issue list based on labels.

        :return: list of documents
        """
        documents = []
        page = 1
        # Loop until there are no more issues
        while True:
            issues: Dict = self._loop.run_until_complete(
                self._github_client.get_issues(
                    self._owner, self._repo, state=state.value, page=page
                )
            )

            if len(issues) == 0:
                print_if_verbose(self._verbose, "No more issues found, stopping")

                break
            print_if_verbose(
                self._verbose, f"Found {len(issues)} issues in the repo page {page}"
            )
            page += 1
            filterCount = 0
            for issue in issues:
                if not self._must_include(labelFilters, issue):
                    filterCount += 1
                    continue
                title = issue["title"]
                body = issue["body"]
                document = Document(
                    doc_id=str(issue["number"]),
                    text=f"{title}\n{body}",
                )
                extra_info = {
                    "state": issue["state"],
                    "created_at": issue["created_at"],
                    # url is the API URL
                    "url": issue["url"],
                    # source is the HTML URL, more conveninent for humans
                    "source": issue["html_url"],
                }
                if issue["closed_at"] is not None:
                    extra_info["closed_at"] = issue["closed_at"]
                if issue["assignee"] is not None:
                    extra_info["assignee"] = issue["assignee"]["login"]
                if issue["labels"] is not None:
                    extra_info["labels"] = [label["name"] for label in issue["labels"]]
                document.extra_info = extra_info
                documents.append(document)

            print_if_verbose(self._verbose, f"Resulted in {len(documents)} documents")
            if labelFilters is not None:
                print_if_verbose(self._verbose, f"Filtered out {filterCount} issues")

        return documents


def read_page(self, page_id: str) -> str:
        """Read a page."""
        return self._read_block(page_id)


def is_risk_title(title: str, filing_type: Optional[str]) -> bool:
    """Checks to see if the title matches the pattern for the risk heading."""
    if filing_type in REPORT_TYPES:
        return is_10k_risk_title(clean_sec_text(title, lowercase=True))
    elif filing_type in S1_TYPES:
        return is_s1_risk_title(clean_sec_text(title, lowercase=True))
    return False


def _configure_optimizer(self, client_optimizer, model_parameters):
        """Config basic optimizer and optimizer.

        Args:
            client_optimizer (torch.optim.Optimizer or callable): client optimizer.
            model_parameters (list): list of model parameters.
        """
        if client_optimizer is not None:
            if isinstance(client_optimizer, tuple(self._supported_optims())):
                client_optimizer.param_groups[:] = [
                    pg for pg in client_optimizer.param_groups if len(pg['params']) != 0
                ]
                log_dist("Removing param_group that has no 'params' in the client Optimizer", ranks=[0])

                basic_optimizer = client_optimizer
                log_dist('Using client Optimizer as basic optimizer', ranks=[0])
            else:
                basic_optimizer = client_optimizer(model_parameters)
                log_dist('Using client callable to create basic optimizer', ranks=[0])
        else:
            basic_optimizer = self._configure_basic_optimizer(model_parameters)
            log_dist(f'Using DeepSpeed Optimizer param name {self.optimizer_name()} as basic optimizer', ranks=[0])

        if self.msamp_enabled():
            optlevel = self.msamp_optlevel()
            if optlevel == 'O3':
                # O3 is for ZeRO and need to cast to O2 for MS-AMP.
                optlevel = 'O2'
            use_te = self.msamp_use_te()
            model, basic_optimizer = msamp_initialize(self.module, basic_optimizer, optlevel, use_te)
            self._set_client_model(model)
            # We need to reset param names after msamp initialize.
            self.param_names = {param: name for name, param in model.named_parameters()}

        self._check_for_duplicates(basic_optimizer)

        self.basic_optimizer = basic_optimizer
        log_dist('DeepSpeed Basic Optimizer = {}'.format(basic_optimizer.__class__.__name__), ranks=[0])

        optimizer_wrapper = self._do_optimizer_sanity_check(basic_optimizer)
        if optimizer_wrapper == ZERO_OPTIMIZATION:
            self.optimizer = self._configure_zero_optimizer(basic_optimizer)
        elif optimizer_wrapper == FP8:
            self.optimizer = self._configure_fp8_optimizer(basic_optimizer, optimizer_wrapper)
        elif optimizer_wrapper == AMP:
            amp_params = self.amp_params()
            log_dist(f'Initializing AMP with these params: {amp_params}', ranks=[0])
            model, self.optimizer = amp.initialize(self.module, basic_optimizer, **amp_params)
            self._set_client_model(model)
            self._broadcast_model()
            # TODO: maybe need to broadcast experts differently?
        elif optimizer_wrapper == FP16:
            self.optimizer = self._configure_fp16_optimizer(basic_optimizer)
        elif optimizer_wrapper == BFLOAT16:
            self.optimizer = self._configure_bf16_optimizer(basic_optimizer)
        else:
            self.optimizer = basic_optimizer

        log_dist('DeepSpeed Final Optimizer = {}'.format(self.optimizer_name()), ranks=[0])

        self.compression_scheduler = self._configure_compression_scheduler()
        self.quantizer = self._configure_quantization()


def __getattr__(self, name):
        """Get attribute by name.

        Args:
            name (str): Attribute name.

        Returns:
            Attribute value.
        """
        return self.__dict__.get(name, getattr(self.__dict__['ctx'], name))


def load_safetensors(self, state_dict_dir):
        """
        Lazily load the safetensors by associating each weight with the filename.
        """
        filename = os.path.join(state_dict_dir, _SAFETENSORS_MODEL_FILENAME)
        with safe_open(filename, framework="pt") as f:
            keys = f.keys()
        key_to_filename = dict(zip(keys, [_SAFETENSORS_MODEL_FILENAME] * len(keys)))
        self._load_from_state_dict_dir(state_dict_dir, key_to_filename)


def export_csv(self, path):
        """
        Export the capture to a CSV file.

        Args:
            path (str): Path to the destination file.

        Returns:
            None
        """

        names = [p.name for p in self._probes]
        values = [self.get_trace(n) for n in names]

        # Transpose list of lists so that data flows top-to-bottom instead of
        # left-to-right
        values_transpose = [list(x) for x in zip(*values)]

        import csv

        with open(path, "w") as f:
            writer = csv.writer(f)

            writer.writerow(names)
            writer.writerows(values_transpose)


@pytest.mark.parametrize('k', [0])
@pytest.mark.parametrize('batch_size', [1, 2, 32])
@pytest.mark.parametrize("acceptance_sampler_method",
                         ["rejection_sampler", "typical_acceptance_sampler"])
@torch.inference_mode()
def test_k_equals_zero(k: int, batch_size: int,
                       acceptance_sampler_method: str):
    """Verify that the SpecDecodeWorker calls the draft and target workers
    when k is zero. This happens during prefill.
    """
    draft_worker = mock_worker(cls=MultiStepWorker)
    target_worker = mock_worker()
    metrics_collector = MagicMock(spec=AsyncMetricsCollector)

    sampler_output = MagicMock(spec=SamplerOutput)
    sampler_output.hidden_states = None
    target_worker.execute_model.return_value = [sampler_output]

    draft_worker.device = 'cuda'
    target_worker.device = 'cuda'

    set_random_seed(1)

    worker = SpecDecodeWorker(
        proposer_worker=draft_worker,
        scorer_worker=target_worker,
        spec_decode_sampler=mock_spec_decode_sampler(
            acceptance_sampler_method),
        disable_logprobs=False,
        metrics_collector=metrics_collector,
    )

    seq_group_metadata_list, _, _ = create_batch(batch_size,
                                                 k,
                                                 prev_output_token_len=0)
    execute_model_req = ExecuteModelRequest(
        seq_group_metadata_list=seq_group_metadata_list, num_lookahead_slots=k)

    out = worker.execute_model(execute_model_req=execute_model_req)

    assert len(out) == 1, f"expected only one token output when {k=}"
    assert out[0].sampled_token_probs is None, (
        "expect gpu tensor references to be None")
    assert out[
        0].sampled_token_ids is None, "expect gpu tensor references to be None"

    draft_worker.execute_model.assert_called_once_with(execute_model_req)
    target_worker.execute_model.assert_called_once_with(execute_model_req)


def mod2pi(self, theta: float) -> float:
		"""
		Perform modulus operation on 2π.
		"""
		return theta - 2.0 * math.pi * math.floor(theta / math.pi / 2.0)


@env.group(name="clear", short_help="Clear an environment directory.", context_settings=context_settings)
def clear() -> None:
    """Clear an environment directory."""


def checkForNCNN() -> bool:
    """
    function that checks if the pytorch backend is available
    """
    try:
        from rife_ncnn_vulkan_python import Rife
        import ncnn

        try:
            from upscale_ncnn_py import UPSCALE
        except Exception:
            printAndLog(
                "Warning: Cannot import upscale_ncnn, falling back to default ncnn processing. (Please install vcredlist on your computer to fix this!)"
            )
        return True
    except ImportError as e:
        log(str(e))
        return False
    except Exception as e:
        log(str(e))


def _to_a3m(sequences: Sequence[str]) -> str:
    """Converts sequences to an a3m file."""
    names = ["sequence %d" % i for i in range(1, len(sequences) + 1)]
    a3m = []
    for sequence, name in zip(sequences, names):
        a3m.append(u">" + name + u"\n")
        a3m.append(sequence + u"\n")
    return "".join(a3m)


async def async_turn_on(self, **kwargs) -> None:
        """Turn light on."""

        if not self.coordinator.client.use_ble_relay:
            raise HomeAssistantError(f'A PetKit BLE relay is required to control {self.wf_data.data["name"]}')
        if not self.wf_data.group_relay:
            raise HomeAssistantError(
                f'A PetKit BLE relay is required to control {self.wf_data.data["name"]}. '
                f'PetKit did not return a valid relay device. If you do have a relay device, '
                f'it may temporarily be offline.'
            )

        try:
            await self.coordinator.client.control_water_fountain(self.wf_data, W5Command.LIGHT_ON)
        except BluetoothError:
            raise PetKitBluetoothError(f'Bluetooth connection to {self.wf_data.data["name"]} failed. Please try turning on the light again.')
        else:
            self.wf_data.data['settings']['lampRingSwitch'] = 1
            self.async_write_ha_state()
            await asyncio.sleep(1)
            await self.coordinator.async_request_refresh()


@property
    def native_value(self) -> str:
        """Always reset to 0,0"""

        return "0,0"


def _init_branch(self,):
        """Initialize classification branch and regression branch of head."""

        fc_cls = Linear(self.embed_dims*self.bbox_size, self.cls_out_channels)
        # fc_cls = Linear(self.embed_dims, self.cls_out_channels)

        reg_branch = []
        for _ in range(self.num_reg_fcs):
            reg_branch.append(Linear(self.embed_dims, self.embed_dims))
            reg_branch.append(nn.LayerNorm(self.embed_dims))
            reg_branch.append(nn.ReLU())

        if self.discrete_output:
            reg_branch.append(nn.Linear(
                self.embed_dims, max(self.canvas_size), bias=True,))
        else:
            reg_branch.append(nn.Linear(
                self.embed_dims, self.coord_dim, bias=True,))

        reg_branch = nn.Sequential(*reg_branch)
        # add sigmoid or not

        def _get_clones(module, N):
            return nn.ModuleList([copy.deepcopy(module) for i in range(N)])

        num_pred = self.transformer.decoder.num_layers

        if self.iterative:
            fc_cls = _get_clones(fc_cls, num_pred)
            reg_branch = _get_clones(reg_branch, num_pred)
        else:
            reg_branch = nn.ModuleList(
                [reg_branch for _ in range(num_pred)])
            fc_cls = nn.ModuleList(
                [fc_cls for _ in range(num_pred)])

        self.pre_branches = nn.ModuleDict([
            ('cls', fc_cls),
            ('reg', reg_branch), ])


def _remove_invalid_boxes(
        self,
        detected_boxes,
        detected_scores,
        detected_class_labels,
        detected_masks=None,
    ):
        """Removes entries with invalid boxes.

    A box is invalid if either its xmax is smaller than its xmin, or its ymax
    is smaller than its ymin.

    Args:
      detected_boxes: A float numpy array of size [num_boxes, 4] containing box
        coordinates in [ymin, xmin, ymax, xmax] format.
      detected_scores: A float numpy array of size [num_boxes].
      detected_class_labels: A int32 numpy array of size [num_boxes].
      detected_masks: A uint8 numpy array of size [num_boxes, height, width].

    Returns:
      valid_detected_boxes: A float numpy array of size [num_valid_boxes, 4]
        containing box coordinates in [ymin, xmin, ymax, xmax] format.
      valid_detected_scores: A float numpy array of size [num_valid_boxes].
      valid_detected_class_labels: A int32 numpy array of size
        [num_valid_boxes].
      valid_detected_masks: A uint8 numpy array of size
        [num_valid_boxes, height, width].
    """
        valid_indices = np.logical_and(
            detected_boxes[:, 0] < detected_boxes[:, 2],
            detected_boxes[:, 1] < detected_boxes[:, 3],
        )
        detected_boxes = detected_boxes[valid_indices]
        detected_scores = detected_scores[valid_indices]
        detected_class_labels = detected_class_labels[valid_indices]
        if detected_masks is not None:
            detected_masks = detected_masks[valid_indices]
        return [
            detected_boxes,
            detected_scores,
            detected_class_labels,
            detected_masks,
        ]


def finalize(self):
        """Performs a final set of operations after logs have been saved."""

        return


def center_of_mass(mask, esp=1e-6):
    """Calculate the centroid coordinates of the mask.

    Args:
        mask (Tensor): The mask to be calculated, shape (h, w).
        esp (float): Avoid dividing by zero. Default: 1e-6.

    Returns:
        tuple[Tensor]: the coordinates of the center point of the mask.

            - center_h (Tensor): the center point of the height.
            - center_w (Tensor): the center point of the width.
    """
    h, w = mask.shape
    grid_h = torch.arange(h, device=mask.device)[:, None]
    grid_w = torch.arange(w, device=mask.device)
    normalizer = mask.sum().float().clamp(min=esp)
    center_h = (mask * grid_h).sum() / normalizer
    center_w = (mask * grid_w).sum() / normalizer
    return center_h, center_w


def _init_predictor(self):
        """Initialize predictor layers of the head."""
        self.conv_cls = nn.Conv2d(
            self.feat_channels, self.cls_out_channels, 3, padding=1)
        self.conv_reg = nn.Conv2d(self.feat_channels, 4, 3, padding=1)


def cty_lookup(self, callsign: str) -> list:
        """Lookup callsign in cty.dat file.

        Parameters
        ----------
        callsign : str
        callsign to lookup

        Returns
        -------
        return : list
        list of dicts containing the callsign and the station.
        """
        callsign = callsign.upper()
        for count in reversed(range(len(callsign))):
            searchitem = callsign[: count + 1]
            result = {
                key: val for key, val in self.ctyfile.items() if key == searchitem
            }
            if not result:
                continue
            if result.get(searchitem).get("exact_match"):
                if searchitem == callsign:
                    return result
                continue
            return result


def change_mode(self, mode: str, intended_freq=None) -> None:
        """
        Change mode to given mode.
        Send the new mode to the rig control.
        Set the band indicator.
        Set the window title.
        Clear the inputs.
        Read the CW macros.

        Parameters
        ----------
        mode : str
        Mode to change to.

        Returns
        -------
        None
        """
        if mode in ("CW", "CW-U", "CW-L", "CWR"):
            if self.rig_control and self.rig_control.online:
                self.rig_control.set_mode(self.rig_control.last_cw_mode)
                if self.pref.get("cwtype") == 3 and self.rig_control is not None:
                    if self.rig_control.interface == "flrig":
                        self.cwspeed_spinbox_changed()
                        self.rig_control.cat.set_flrig_cw_send(True)
            else:
                self.setmode("CW")
                self.radio_state["mode"] = "CW"
                band = getband(str(self.radio_state.get("vfoa", "0.0")))
                self.set_band_indicator(band)
            self.set_window_title()
            self.clearinputs()
            self.read_macros()
            return
        if mode in (
            "DIGI-U",
            "DIGI-L",
            "RTTY",
            "RTTY-R",
            "LSB-D",
            "USB-D",
            "AM-D",
            "FM-D",
        ):
            if self.rig_control and self.rig_control.online:
                self.rig_control.set_mode(self.rig_control.last_data_mode)
            else:
                self.radio_state["mode"] = "RTTY"
            self.setmode("RTTY")
            band = getband(str(self.radio_state.get("vfoa", "0.0")))
            self.set_band_indicator(band)
            self.set_window_title()
            self.clearinputs()
            self.read_macros()
            return
        if mode == "SSB":
            if intended_freq:
                freq = intended_freq
            else:
                freq = int(self.radio_state.get("vfoa", 0))

            if freq > 10000000:
                self.radio_state["mode"] = "USB"
            else:
                self.radio_state["mode"] = "LSB"

            if self.rig_control and self.rig_control.online:
                self.rig_control.set_mode(self.radio_state.get("mode"))
            else:
                self.setmode("SSB")
                band = getband(str(self.radio_state.get("vfoa", "0.0")))
                self.set_band_indicator(band)
            self.set_window_title()
            self.clearinputs()
            self.read_macros()


def preprocess(
    img: np.ndarray, out_bbox, input_size: Tuple[int, int] = (192, 256)
) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
    """Do preprocessing for DWPose model inference.

    Args:
        img (np.ndarray): Input image in shape.
        input_size (tuple): Input image size in shape (w, h).

    Returns:
        tuple:
        - resized_img (np.ndarray): Preprocessed image.
        - center (np.ndarray): Center of image.
        - scale (np.ndarray): Scale of image.
    """
    # get shape of image
    img_shape = img.shape[:2]
    out_img, out_center, out_scale = [], [], []
    if len(out_bbox) == 0:
        out_bbox = [[0, 0, img_shape[1], img_shape[0]]]
    for i in range(len(out_bbox)):
        x0 = out_bbox[i][0]
        y0 = out_bbox[i][1]
        x1 = out_bbox[i][2]
        y1 = out_bbox[i][3]
        bbox = np.array([x0, y0, x1, y1])

        # get center and scale
        center, scale = bbox_xyxy2cs(bbox, padding=1.25)

        # do affine transformation
        resized_img, scale = top_down_affine(input_size, scale, center, img)

        # normalize image
        mean = np.array([123.675, 116.28, 103.53])
        std = np.array([58.395, 57.12, 57.375])
        resized_img = (resized_img - mean) / std

        out_img.append(resized_img)
        out_center.append(center)
        out_scale.append(scale)

    return out_img, out_center, out_scale


def __init__(self):
        """
        Init method.
        """
        super().__init__()


def forward(self, coeffs):
        """
        Args:
            coeffs (yl, yh): tuple of lowpass and bandpass coefficients, should
              match the format returned by DWT1DForward.

        Returns:
            Reconstructed input of shape :math:`(N, C_{in}, L_{in})`

        Note:
            Can have None for any of the highpass scales and will treat the
            values as zeros (not in an efficient way though).
        """
        x0, highs = coeffs
        assert x0.ndim == 3, "Can only handle 3d inputs (N, C, L)"
        mode = mode_to_int(self.mode)
        # Do a multilevel inverse transform
        for x1 in highs[::-1]:
            if x1 is None:
                x1 = torch.zeros_like(x0)

            # 'Unpad' added signal
            if x0.shape[-1] > x1.shape[-1]:
                x0 = x0[..., :-1]
            x0 = SFB1D.apply(x0, x1, self.g0, self.g1, mode, self.use_amp)
        return x0


def get_auth_args():
    """
    Generates a parser which is used to get all of the authentication information
    """
    parser = ArgumentParser(
        description='TikTok Auth is a program which can log you into multiple accounts sequentially'
    )

    # authentication arguments
    parser.add_argument('-o', '--output', default='tmp',
                        help='The output folder to save the cookies to')
    parser.add_argument('-i', '--input', help='A csv file with username and password')
    # parser.add_argument('-h', '--header', default=True,
    # help='The header of the csv file which contains the username and password')
    parser.add_argument('-u', '--username', help='Your TikTok email / username')
    parser.add_argument('-p', '--password', help='Your TikTok password')

    return parser.parse_args()


def get_transfer_statistics(self, data=None):
        """
        查询转移历史统计数据
        """
        MovieChartLabels = []
        MovieNums = []
        TvChartData = {}
        TvNums = []
        AnimeNums = []
        for statistic in self.dbhelper.get_transfer_statistics():
            if statistic[0] == "电影":
                MovieChartLabels.append(statistic[1])
                MovieNums.append(statistic[2])
            else:
                if not TvChartData.get(statistic[1]):
                    TvChartData[statistic[1]] = {"tv": 0, "anime": 0}
                if statistic[0] == "电视剧":
                    TvChartData[statistic[1]]["tv"] += statistic[2]
                elif statistic[0] == "动漫":
                    TvChartData[statistic[1]]["anime"] += statistic[2]
        TvChartLabels = list(TvChartData)
        for tv_data in TvChartData.values():
            TvNums.append(tv_data.get("tv"))
            AnimeNums.append(tv_data.get("anime"))

        return {
            "code": 0,
            "MovieChartLabels": MovieChartLabels,
            "MovieNums": MovieNums,
            "TvChartLabels": TvChartLabels,
            "TvNums": TvNums,
            "AnimeNums": AnimeNums
        }

"""
        查询转移历史统计数据
        """


@filterrule.doc(parser=parser)
    def post(self):
        """
        新增/修改规则
        """
        return WebAction().api_action(cmd='add_filterrule', data=self.parser.parse_args())


@staticmethod
    def is_luba1(device_name: str, product_key: str = ""):
        """Check if the given device is of type LUBA.

        This function determines if the device specified by 'device_name' is of
        type LUBA. If 'product_key' is provided, it is used to further identify
        the device type.

        Args:
            device_name (str): The name of the device.
            product_key (str?): The product key associated with the device. Defaults to "".

        Returns:
            bool: True if the device is of type LUBA, False otherwise.

        """

        if not product_key:
            device_type = DeviceType.value_of_str(device_name)
        else:
            device_type = DeviceType.value_of_str(device_name, product_key)

        return device_type.get_value() == DeviceType.LUBA.get_value()


def update(oids, hids, dists, indices, events, m):
    """
        tracks : my results of shape {tr_id: {'id', 'im_index', 'max_iou', 'bbox'}
        num_frames : number of frames
    """
    import pandas as pd
    asso = dict()
    hypo = dict()
    cols = ['Type', 'id', 'frame', 'tr_id', 'iou', 'w', 'h']
    events = pd.DataFrame(columns=cols)
    for i in range(num_frames):
        for tr_id, tr in self.tracks.items():
            for t in tr:
                if t['im_index'] == i:
                    if t['id'] in asso.keys():
                        h_o = asso[t['id']]
                        if tr_id == h_o:
                            TYPE = 'match'
                        else:
                            if h_o in hypo.keys():
                                TYPE = 'switch'
                            else:
                                TYPE = 'ascend'
                    elif tr_id == -1:
                        TYPE = 'fp'
                    elif tr_id in hypo.keys():
                        if t['id'] not in asso.keys():
                            TYPE = 'migrate'
                        elif hypo[tr_id] != t['id']:
                            TYPE = 'transfer'
                    df = pd.DataFrame([[TYPE, t['id'], i, tr_id, t['iou'], t['bbox']
                                      [2]-t['bbox'][0], t['bbox'][3]-t['bbox'][1]]], columns=cols)

    #self.dirty_events = True
    oids = np.asarray(oids)
    oids_masked = np.zeros_like(oids, dtype=np.bool)
    hids = np.asarray(hids)
    hids_masked = np.zeros_like(hids, dtype=np.bool)
    dists = np.atleast_2d(dists).astype(float).reshape(
        oids.shape[0], hids.shape[0]).copy()

    if frameid is None:
        assert self.auto_id, 'auto-id is not enabled'
        if len(self._indices['FrameId']) > 0:
            frameid = self._indices['FrameId'][-1] + 1
        else:
            frameid = 0
    else:
        assert not self.auto_id, 'Cannot provide frame id when auto-id is enabled'

    eid = itertools.count()

    # 0. Record raw events

    no = len(oids)
    nh = len(hids)

    # Add a RAW event simply to ensure the frame is counted.
    indices.append(frameid, next(eid))
    events.append('RAW', np.nan, np.nan, np.nan)

    # There must be at least one RAW event per object and hypothesis.
    # Record all finite distances as RAW events.
    valid_i, valid_j = np.where(np.isfinite(dists))
    valid_dists = dists[valid_i, valid_j]
    for i, j, dist_ij in zip(valid_i, valid_j, valid_dists):
        indices.append(frameid, next(eid))
        events.append('RAW', oids[i], hids[j], dist_ij)
    # Add a RAW event for objects and hypotheses that were present but did
    # not overlap with anything.
    used_i = np.unique(valid_i)
    used_j = np.unique(valid_j)
    unused_i = np.setdiff1d(np.arange(no), used_i)
    unused_j = np.setdiff1d(np.arange(nh), used_j)
    for oid in oids[unused_i]:
        indices.append(frameid, next(eid))
        events.append('RAW', oid, np.nan, np.nan)
    for hid in hids[unused_j]:
        indices.append(frameid, next(eid))
        events.append('RAW', np.nan, hid, np.nan)

    if oids.size * hids.size > 0:
        # 1. Try to re-establish tracks from previous correspondences
        for i in range(oids.shape[0]):
            # No need to check oids_masked[i] here.
            if oids[i] not in self.m:
                continue

            hprev = self.m[oids[i]]
            j, = np.where(~hids_masked & (hids == hprev))
            if j.shape[0] == 0:
                continue
            j = j[0]

            if np.isfinite(dists[i, j]):
                o = oids[i]
                h = hids[j]
                oids_masked[i] = True
                hids_masked[j] = True
                self.m[oids[i]] = hids[j]

                indices.append(frameid, next(eid))
                events.append('MATCH', oids[i], hids[j], dists[i, j])
                self.last_match[o] = frameid
                self.hypHistory[h] = frameid

        # 2. Try to remaining objects/hypotheses
        dists[oids_masked, :] = np.nan
        dists[:, hids_masked] = np.nan

        rids, cids = linear_sum_assignment(dists)

        for i, j in zip(rids, cids):
            if not np.isfinite(dists[i, j]):
                continue

            o = oids[i]
            h = hids[j]
            is_switch = (o in self.m and
                         self.m[o] != h and
                         abs(frameid - self.last_occurrence[o]) <= self.max_switch_time)
            cat1 = 'SWITCH' if is_switch else 'MATCH'
            if cat1 == 'SWITCH':
                if h not in self.hypHistory:
                    subcat = 'ASCEND'
                    indices.append(frameid, next(eid))
                    events.append(subcat, oids[i], hids[j], dists[i, j])
            # ignore the last condition temporarily
            is_transfer = (h in self.res_m and
                           self.res_m[h] != o)
            # is_transfer = (h in self.res_m and
            #                self.res_m[h] != o and
            #                abs(frameid - self.last_occurrence[o]) <= self.max_switch_time)
            cat2 = 'TRANSFER' if is_transfer else 'MATCH'
            if cat2 == 'TRANSFER':
                if o not in self.last_match:
                    subcat = 'MIGRATE'
                    indices.append(frameid, next(eid))
                    events.append(subcat, oids[i], hids[j], dists[i, j])
                indices.append(frameid, next(eid))
                events.append(cat2, oids[i], hids[j], dists[i, j])
            if vf != '' and (cat1 != 'MATCH' or cat2 != 'MATCH'):
                if cat1 == 'SWITCH':
                    vf.write('%s %d %d %d %d %d\n' % (
                        subcat[:2], o, self.last_match[o], self.m[o], frameid, h))
                if cat2 == 'TRANSFER':
                    vf.write('%s %d %d %d %d %d\n' % (
                        subcat[:2], h, self.hypHistory[h], self.res_m[h], frameid, o))
            self.hypHistory[h] = frameid
            self.last_match[o] = frameid
            indices.append(frameid, next(eid))
            events.append(cat1, oids[i], hids[j], dists[i, j])
            oids_masked[i] = True
            hids_masked[j] = True
            self.m[o] = h
            self.res_m[h] = o

    # 3. All remaining objects are missed
    for o in oids[~oids_masked]:
        indices.append(frameid, next(eid))
        events.append('MISS', o, np.nan, np.nan)
        if vf != '':
            vf.write('FN %d %d\n' % (frameid, o))

    # 4. All remaining hypotheses are false alarms
    for h in hids[~hids_masked]:
        indices.append(frameid, next(eid))
        events.append('FP', np.nan, h, np.nan)
        if vf != '':
            vf.write('FP %d %d\n' % (frameid, h))

    # 5. Update occurance state
    for o in oids:
        self.last_occurrence[o] = frameid

    return frameid


def checkpoint_filter_fn(state_dict, model):
    """ convert patch embedding weight from manual patchify + linear proj to conv"""
    out_dict = {}
    if 'model' in state_dict:
        # For deit models
        state_dict = state_dict['model']
    for k, v in state_dict.items():
        if 'patch_embed.proj.weight' in k and len(v.shape) < 4:
            # For old models that I trained prior to conv based patchification
            O, I, H, W = model.patch_embed.proj.weight.shape
            v = v.reshape(O, -1, H, W)
        elif k == 'pos_embed' and v.shape != model.pos_embed.shape:
            # To resize pos embedding when using model at different size from pretrained weights
            v = resize_pos_embed(v, model.pos_embed, getattr(model, 'num_tokens', 1),
                                                model.patch_embed.grid_size)
        out_dict[k] = v
    return out_dict


def setup_filters(self, filter_cls, filter_args):
        "Initializes the explicit and implicit filters"
        assert self.order >= 2, f'Order must be at least 2, (got {self.order})'
        total_width = self.d_model * self.inner_factor * (self.order + 1)

        self.short_filter = nn.Conv1d(
            in_channels=total_width,
            out_channels=total_width,
            kernel_size=self.short_filter_order,
            groups=total_width,
            padding=self.short_filter_order - 1
        )

        filter_cls = instantiate(registry.layer, filter_cls, partial=True)

        self.filter_fn = filter_cls(
            self.head_dim * self.inner_factor * (self.order - 1),
            order=self.filter_order,
            seq_len=self.l_max,
            channels=1,
            dropout=self.filter_dropout,
            **filter_args
        )
        if self.jit_filter: self.filter_fn = torch.jit.script(self.filter_fn, self.L)


@mmcv.jit(derivate=True, coderize=True)
def custom_weight_dir_reduce_loss(loss, weight=None, reduction='mean', avg_factor=None):
    """Apply element-wise weight and reduce loss.

    Args:
        loss (Tensor): num_sample, num_dir
        weight (Tensor): Element-wise weights.
        reduction (str): Same as built-in losses of PyTorch.
        avg_factor (float): Average factor when computing the mean of losses.

    Returns:
        Tensor: Processed loss values.
    """
    # if weight is specified, apply element-wise weight
    if weight is not None:
        loss = loss * weight

    # if avg_factor is not specified, just reduce the loss
    if avg_factor is None:
        raise ValueError('avg_factor should not be none for OrderedPtsL1Loss')
        # loss = reduce_loss(loss, reduction)
    else:
        # if reduction is mean, then average the loss by avg_factor
        if reduction == 'mean':
            # import pdb;pdb.set_trace()
            # loss = loss.permute(1,0,2,3).contiguous()
            loss = loss.sum()
            loss = loss / avg_factor
        # if reduction is 'none', then do nothing, otherwise raise an error
        elif reduction != 'none':
            raise ValueError('avg_factor can not be used with reduction="sum"')
    return loss


def add_model_config(path):
    """add model config path or file and update registry"""
    if not isinstance(path, Path):
        path = Path(path)
    _MODEL_CONFIG_PATHS.append(path)
    _rescan_model_configs()


@staticmethod
    def set_config_value(cfg, cfg_key, cfg_value):
        """
        根据Key设置配置值
        """
        # 密码
        if cfg_key == "app.login_password":
            if cfg_value and not cfg_value.startswith("[hash]"):
                cfg['app']['login_password'] = "[hash]%s" % generate_password_hash(
                    cfg_value)
            else:
                cfg['app']['login_password'] = cfg_value or "password"
            return cfg
        # 代理
        if cfg_key == "app.proxies":
            if cfg_value:
                if not cfg_value.startswith("http") and not cfg_value.startswith("sock"):
                    cfg['app']['proxies'] = {
                        "https": "http://%s" % cfg_value, "http": "http://%s" % cfg_value}
                else:
                    cfg['app']['proxies'] = {"https": "%s" %
                                             cfg_value, "http": "%s" % cfg_value}
            else:
                cfg['app']['proxies'] = {"https": None, "http": None}
            return cfg
        # 豆瓣用户列表
        if cfg_key == "douban.users":
            vals = cfg_value.split(",")
            cfg['douban']['users'] = vals
            return cfg
        # 索引器
        if cfg_key == "jackett.indexers":
            vals = cfg_value.split("\n")
            cfg['jackett']['indexers'] = vals
            return cfg
        # 最大支持三层赋值
        keys = cfg_key.split(".")
        if keys:
            if len(keys) == 1:
                cfg[keys[0]] = cfg_value
            elif len(keys) == 2:
                if not cfg.get(keys[0]):
                    cfg[keys[0]] = {}
                cfg[keys[0]][keys[1]] = cfg_value
            elif len(keys) == 3:
                if cfg.get(keys[0]):
                    if not cfg[keys[0]].get(keys[1]) or isinstance(cfg[keys[0]][keys[1]], str):
                        cfg[keys[0]][keys[1]] = {}
                    cfg[keys[0]][keys[1]][keys[2]] = cfg_value
                else:
                    cfg[keys[0]] = {}
                    cfg[keys[0]][keys[1]] = {}
                    cfg[keys[0]][keys[1]][keys[2]] = cfg_value

        return cfg


async def post(self) -> "MultiDictProxy[Union[str, bytes, FileField]]":
        """Return POST parameters."""
        if self._post is not None:
            return self._post
        if self._method not in self.POST_METHODS:
            self._post = MultiDictProxy(MultiDict())
            return self._post

        content_type = self.content_type
        if content_type not in (
            "",
            "application/x-www-form-urlencoded",
            "multipart/form-data",
        ):
            self._post = MultiDictProxy(MultiDict())
            return self._post

        out: MultiDict[Union[str, bytes, FileField]] = MultiDict()

        if content_type == "multipart/form-data":
            multipart = await self.multipart()
            max_size = self._client_max_size

            field = await multipart.next()
            while field is not None:
                size = 0
                field_ct = field.headers.get(hdrs.CONTENT_TYPE)

                if isinstance(field, BodyPartReader):
                    assert field.name is not None

                    # Note that according to RFC 7578, the Content-Type header
                    # is optional, even for files, so we can't assume it's
                    # present.
                    # https://tools.ietf.org/html/rfc7578#section-4.4
                    if field.filename:
                        # store file in temp file
                        tmp = tempfile.TemporaryFile()
                        chunk = await field.read_chunk(size=2**16)
                        while chunk:
                            chunk = field.decode(chunk)
                            tmp.write(chunk)
                            size += len(chunk)
                            if 0 < max_size < size:
                                tmp.close()
                                raise HTTPRequestEntityTooLarge(
                                    max_size=max_size, actual_size=size
                                )
                            chunk = await field.read_chunk(size=2**16)
                        tmp.seek(0)

                        if field_ct is None:
                            field_ct = "application/octet-stream"

                        ff = FileField(
                            field.name,
                            field.filename,
                            cast(io.BufferedReader, tmp),
                            field_ct,
                            field.headers,
                        )
                        out.add(field.name, ff)
                    else:
                        # deal with ordinary data
                        value = await field.read(decode=True)
                        if field_ct is None or field_ct.startswith("text/"):
                            charset = field.get_charset(default="utf-8")
                            out.add(field.name, value.decode(charset))
                        else:
                            out.add(field.name, value)
                        size += len(value)
                        if 0 < max_size < size:
                            raise HTTPRequestEntityTooLarge(
                                max_size=max_size, actual_size=size
                            )
                else:
                    raise ValueError(
                        "To decode nested multipart you need " "to use custom reader",
                    )

                field = await multipart.next()
        else:
            data = await self.read()
            if data:
                charset = self.charset or "utf-8"
                out.extend(
                    parse_qsl(
                        data.rstrip().decode(charset),
                        keep_blank_values=True,
                        encoding=charset,
                    )
                )

        self._post = MultiDictProxy(out)
        return self._post


def add_put(self, path: str, handler: Handler, **kwargs: Any) -> AbstractRoute:
        """Shortcut for add_route with method PUT."""
        return self.add_route(hdrs.METH_PUT, path, handler, **kwargs)


def create_memory_object_stream(
    max_buffer_size: float = 0, item_type: type[T_Item] | None = None
) -> tuple[MemoryObjectSendStream[Any], MemoryObjectReceiveStream[Any]]:
    """
    Create a memory object stream.

    :param max_buffer_size: number of items held in the buffer until ``send()`` starts blocking
    :param item_type: type of item, for marking the streams with the right generic type for
        static typing (not used at run time)
    :return: a tuple of (send stream, receive stream)

    """
    if max_buffer_size != math.inf and not isinstance(max_buffer_size, int):
        raise ValueError("max_buffer_size must be either an integer or math.inf")
    if max_buffer_size < 0:
        raise ValueError("max_buffer_size cannot be negative")

    state: MemoryObjectStreamState = MemoryObjectStreamState(max_buffer_size)
    return MemoryObjectSendStream(state), MemoryObjectReceiveStream(state)


def _colors_to_code(self, fg_color: str, bg_color: str) -> Iterable[str]:
        """
        Return a tuple with the vt100 values  that represent this color.
        """
        # When requesting ANSI colors only, and both fg/bg color were converted
        # to ANSI, ensure that the foreground and background color are not the
        # same. (Unless they were explicitly defined to be the same color.)
        fg_ansi = ""

        def get(color: str, bg: bool) -> list[int]:
            nonlocal fg_ansi

            table = BG_ANSI_COLORS if bg else FG_ANSI_COLORS

            if not color or self.color_depth == ColorDepth.DEPTH_1_BIT:
                return []

            # 16 ANSI colors. (Given by name.)
            elif color in table:
                return [table[color]]

            # RGB colors. (Defined as 'ffffff'.)
            else:
                try:
                    rgb = self._color_name_to_rgb(color)
                except ValueError:
                    return []

                # When only 16 colors are supported, use that.
                if self.color_depth == ColorDepth.DEPTH_4_BIT:
                    if bg:  # Background.
                        if fg_color != bg_color:
                            exclude = [fg_ansi]
                        else:
                            exclude = []
                        code, name = _16_bg_colors.get_code(rgb, exclude=exclude)
                        return [code]
                    else:  # Foreground.
                        code, name = _16_fg_colors.get_code(rgb)
                        fg_ansi = name
                        return [code]

                # True colors. (Only when this feature is enabled.)
                elif self.color_depth == ColorDepth.DEPTH_24_BIT:
                    r, g, b = rgb
                    return [(48 if bg else 38), 2, r, g, b]

                # 256 RGB colors.
                else:
                    return [(48 if bg else 38), 5, _256_colors[rgb]]

        result: list[int] = []
        result.extend(get(fg_color, False))
        result.extend(get(bg_color, True))

        return map(str, result)


def extract_from_urllib3():
    """
    Undo monkey-patching by :func:`inject_into_urllib3`.
    """
    util.SSLContext = orig_util_SSLContext
    util.ssl_.SSLContext = orig_util_SSLContext
    util.HAS_SNI = orig_util_HAS_SNI
    util.ssl_.HAS_SNI = orig_util_HAS_SNI
    util.IS_SECURETRANSPORT = False
    util.ssl_.IS_SECURETRANSPORT = False


@property
    def hostname(self):
        """For backwards-compatibility with urlparse. We're nice like that."""
        return self.host


def test_decomposition_nested(self):
        """Tests decompositions of nested controlled operations"""

        ctrl_op = C_ctrl(C_ctrl(lambda: qml.RZ(0.123, wires=0), control=1), control=2)()
        expected = [
            qml.ops.Controlled(qml.RZ(0.123, wires=0), control_wires=[1, 2]),
        ]
        assert ctrl_op.decomposition() == expected


@pytest.mark.xfail(
    reason="QJIT fails with ValueError: Eagerly computing the adjoint (lazy=False) is only supported on single operators."
)
def test_pattern_matching_optimization(backend):
    """Test pattern_matching_optimization"""

    def qnode_builder(device_name):
        """Builder"""

        ops = [qml.S(0), qml.S(0), qml.Z(0)]
        pattern = qml.tape.QuantumTape(ops)

        @partial(qml.transforms.pattern_matching_optimization, pattern_tapes=[pattern])
        @qml.qnode(qml.device(device_name, wires=5))
        def qfunc():
            qml.S(wires=0)
            qml.Z(0)
            qml.S(wires=1)
            qml.CZ(wires=[0, 1])
            qml.S(wires=1)
            qml.S(wires=2)
            qml.CZ(wires=[1, 2])
            qml.S(wires=2)
            return qml.expval(qml.X(0))

        return qfunc

    qnode_control = qnode_builder("default.qubit")
    qnode_backend = qnode_builder(backend)

    jax_jit = jax.jit(qnode_control)
    compiled = qjit(qnode_backend)

    expected = jax_jit()
    observed = compiled()
    _, expected_shape = jax.tree_util.tree_flatten(expected)
    _, observed_shape = jax.tree_util.tree_flatten(observed)

    assert np.allclose(expected, observed)
    assert expected_shape == observed_shape


def forward(self,
                query,
                key,
                value,
                query_pos=None,
                key_pos=None,
                attn_masks=None,
                query_key_padding_mask=None,
                key_padding_mask=None,
                **kwargs):
        """Forward function for `TransformerCoder`.

        Args:
            query (Tensor): Input query with shape
                `(num_queries, bs, embed_dims)`.
            key (Tensor): The key tensor with shape
                `(num_keys, bs, embed_dims)`.
            value (Tensor): The value tensor with shape
                `(num_keys, bs, embed_dims)`.
            query_pos (Tensor): The positional encoding for `query`.
                Default: None.
            key_pos (Tensor): The positional encoding for `key`.
                Default: None.
            attn_masks (List[Tensor], optional): Each element is 2D Tensor
                which is used in calculation of corresponding attention in
                operation_order. Default: None.
            query_key_padding_mask (Tensor): ByteTensor for `query`, with
                shape [bs, num_queries]. Only used in self-attention
                Default: None.
            key_padding_mask (Tensor): ByteTensor for `query`, with
                shape [bs, num_keys]. Default: None.

        Returns:
            Tensor:  results with shape [num_queries, bs, embed_dims].
        """
        for layer in self.layers:
            query = layer(
                query,
                key,
                value,
                query_pos=query_pos,
                key_pos=key_pos,
                attn_masks=attn_masks,
                query_key_padding_mask=query_key_padding_mask,
                key_padding_mask=key_padding_mask,
                **kwargs)
        return query


@classmethod
    def v1_from_args(
        cls, vocab_size: int, *, num_layers: int, hidden_dim: int, num_heads: int
    ) -> CausalLM:
        """Build a v1 Causal LM.

        Args:
            vocab_size: The vocabulary size.
            num_layers: The number of transformer layers.
            hidden_dim: The model hidden dimension.
            num_heads: THe number of attention heads.

        Returns:
            Initialized model.
        """
        model = CausalLM(
            decoder=Decoder(
                attention_mask=ALiBiAttentionLogitBiasLayer(num_heads),
                emb=TransformerEmbeddings(Embedding(vocab_size, embedding_dim=hidden_dim)),
                transformer=StackedTransformerLayer(
                    num_layers,
                    layer=TransformerLayer(
                        self_attention=TransformerAttentionLayer(
                            target_dim=hidden_dim,
                            source_dim=hidden_dim,
                            num_heads=num_heads,
                            structure="prenorm",
                            norm="rmsnorm",
                            qkv_linear_cls=FusedQKVLinear,
                            linear_biases=False,
                        ),
                        feed_forward=TransformerFeedForwardLayer(
                            input_dim=hidden_dim,
                            hidden_dim=round(hidden_dim * (21.0 / 8.0)),
                            activation=(
                                _torch_activation_fn("nn.silu"),
                                _torch_activation_fn("linear"),
                            ),
                            structure="prenorm",
                            norm="rmsnorm",
                            linear_biases=False,
                        ),
                    ),
                ),
                output_norm="rmsnorm",
            )
        )
        return model


def __init__(
        self,
        *,
        input_size: tuple[int, int],
        num_masking_patches: int,
        num_attempts: int = 10,
        min_mask_patches: int = 16,
        min_aspect: float = 0.3,
        max_mask_patches: Optional[int] = None,
        max_aspect: Optional[float] = None,
    ):
        """Initializes MaskingGenerator.

        Args:
            input_size: an int tuple that represents (height, width) of the patchified target.
            num_masking_patches: the number of patches to be masked.
            num_attempts: the max number of attempts for one mask generation trial.
            min_mask_patches: the min number of patches for one masking area.
            max_mask_patches: the max number of patches for one masking area. If None, sets to
                num_masking_patches.
            min_aspect: the min aspect ratio (height/width) for one masking area.
            max_aspect: the max aspect ratio for one masking area. If None, sets to 1 / min_aspect.

        Raises:
            ValueError: if min_aspect or max_aspect are below 0 or max_aspect is smaller than
                min_aspect.
        """
        self.height, self.width = input_size
        # Total number of patches in the pachified input.
        self.num_patches = self.height * self.width
        self.num_masking_patches = num_masking_patches
        self.num_attempts = num_attempts
        self.min_mask_patches = min_mask_patches
        self.max_mask_patches = (
            num_masking_patches if max_mask_patches is None else max_mask_patches
        )
        max_aspect = max_aspect or 1 / min_aspect
        if min_aspect <= 0 or max_aspect <= 0:
            raise ValueError("Both min and max aspect ratios need to be positive.")
        if min_aspect > max_aspect:
            raise ValueError("min_aspect needs to be no greater than max_aspect.")
        self.log_aspect_ratio = (math.log(min_aspect), math.log(max_aspect))


@property
    def endpoints_dims(self) -> dict[str, int]:
        """A dict of {endpoint: dim} specifies dimension of intermediate representations."""
        return self._endpoints_dims


def spatial_encoding(td: TensorDict):
    """We use a spatial encoing as proposed in GraphFormer (https://arxiv.org/abs/2106.05234)
    The spatial encoding in GraphFormer determines the distance of the shortest path between and
    nodes i and j and uses a special value for node pairs that cannot be connected at all.
    For any two operations i<j of the same job, we determine the number of operations to be completet
    when starting at i before j can be started (e.g. i=3 and j=5 -> e=2) and for i>j the negative number of
    operations that starting from j, have been completet before arriving at i (e.g. i=5 j=3 -> e=-2).
    For i=j we set e=0 as well as for operations of different jobs.

    :param torch.Tensor[bs, n_ops] ops_job_map: tensor specifying the index of its corresponding job
    :return torch.Tensor[bs, n_ops, n_ops]: length of shortest path between any two operations
    """
    bs, _, n_total_ops = td["job_ops_adj"].shape
    max_ops_per_job = int(td["job_ops_adj"].sum(-1).max())
    ops_job_map = td["ops_job_map"]
    pad_mask = td["pad_mask"]

    same_job = (ops_job_map[:, None] == ops_job_map[..., None]).to(torch.int32)
    # mask padded
    same_job[pad_mask.unsqueeze(2).expand_as(same_job)] = 0
    same_job[pad_mask.unsqueeze(1).expand_as(same_job)] = 0
    # take upper triangular of same_job and set diagonal to zero for counting purposes
    upper_tri = torch.triu(same_job) - torch.diag(
        torch.ones(n_total_ops, device=td.device)
    )[None].expand_as(same_job)
    # cumsum and masking of operations that do not belong to the same job
    num_jumps = upper_tri.cumsum(2) * upper_tri
    # mirror the matrix
    num_jumps = num_jumps + num_jumps.transpose(1, 2)
    # NOTE: shifted this logic into the spatial encoding module
    # num_jumps = num_jumps + (-num_jumps.transpose(1,2))
    assert not torch.any(num_jumps >= max_ops_per_job)
    # special value for ops of different jobs and self-loops
    num_jumps = torch.where(num_jumps == 0, -1, num_jumps)
    self_mask = torch.eye(n_total_ops).repeat(bs, 1, 1).bool()
    num_jumps[self_mask] = 0
    return num_jumps


def _create_examples(self, lines, set_type):
        """Creates examples for the training and dev sets."""
        examples = []
        for (i, line) in enumerate(lines):
            guid = "%s-%s" % (set_type, i)
            text_a = line[3]
            label = line[1]
            examples.append(
                InputExample(guid=guid,
                             text_a=text_a,
                             text_b=None,
                             label=label))
        return examples


async def _get_database_proxy(self, **kwargs) -> DatabaseProxy:
        """Gets the database proxy."""
        try:
            if await self._does_database_exist():
                return self.cosmos_client.get_database_client(self.database_name)

            if self.create_database:
                return await self.cosmos_client.create_database(self.database_name, **kwargs)
            raise VectorStoreOperationException(f"Database '{self.database_name}' does not exist.")
        except Exception as e:
            raise VectorStoreOperationException(f"Failed to get database proxy for '{id}'.") from e


def _get_underlying_type(annotation: Any) -> Any:
    """Get the underlying type of the annotation."""
    if isinstance(annotation, types.UnionType):
        return _get_non_none_type(annotation.__args__)

    if hasattr(annotation, "__origin__"):
        if annotation.__origin__ is Union:
            return _get_non_none_type(get_args(annotation))

        if isinstance(annotation.__origin__, types.UnionType):
            return _get_non_none_type(annotation.__origin__.__args__)

        return annotation.__origin__

    return annotation


async def get_collections(self) -> list[str]:
        """Nullifies behavior of SemanticTextMemoryBase get_collections."""
        return []


@pytest.fixture
def azure_cognitive_search_memory_store(azure_ai_search_unit_test_env):
    """Fixture to instantiate AzureCognitiveSearchMemoryStore with basic configuration."""
    return AzureCognitiveSearchMemoryStore(
        1536, "https://test.search.windows.net", azure_credentials=AzureKeyCredential("test_key")
    )


def forward(self, *xs):
        """Forward pass.

        Returns:
            tensor: output
        """
        output = xs[0]

        if len(xs) == 2:
            res = self.resConfUnit1(xs[1])
            output = self.skip_add.add(output, res)
            # output += res

        output = self.resConfUnit2(output)

        output = nn.functional.interpolate(
            output, scale_factor=2, mode="bilinear", align_corners=self.align_corners
        )

        output = self.out_conv(output)

        return output


def posedict_to_pose(posedict: Dict[str, float]) -> List[float]:
    """Convert a posedict (from an emotion JSON) into a list of morph values (in the order the models expect them)."""
    # sanity check
    unrecognized_keys = set(posedict.keys()) - set(posedict_keys)
    if unrecognized_keys:
        logger.warning(f"posedict_to_pose: ignoring unrecognized keys in posedict: {unrecognized_keys}")
    # Missing keys are fine - keys for zero values can simply be omitted.

    pose = [0.0 for i in range(len(posedict_keys))]
    for idx, key in enumerate(posedict_keys):
        pose[idx] = posedict.get(key, 0.0)
    return pose


def to_tensor(self, dtype, device):
        """See :func:`BaseInstanceMasks.to_tensor`."""
        if len(self.masks) == 0:
            return torch.empty((0, self.height, self.width),
                               dtype=dtype,
                               device=device)
        ndarray_masks = self.to_ndarray()
        return torch.tensor(ndarray_masks, dtype=dtype, device=device)


def __call__(self, results):
        """Call function to load proposals from file.

        Args:
            results (dict): Result dict from :obj:`mmdet.CustomDataset`.

        Returns:
            dict: The dict contains loaded proposal annotations.
        """

        proposals = results['proposals']
        if proposals.shape[1] not in (4, 5):
            raise AssertionError(
                'proposals should have shapes (n, 4) or (n, 5), '
                f'but found {proposals.shape}')
        proposals = proposals[:, :4]

        if self.num_max_proposals is not None:
            proposals = proposals[:self.num_max_proposals]

        if len(proposals) == 0:
            proposals = np.array([[0, 0, 0, 0]], dtype=np.float32)
        results['proposals'] = proposals
        results['bbox_fields'].append('proposals')
        return results


def forward(self, x):
        """Forward function."""
        if self.num_branches == 1:
            return [self.branches[0](x[0])]

        for i in range(self.num_branches):
            x[i] = self.branches[i](x[i])

        x_fuse = []
        for i in range(len(self.fuse_layers)):
            y = 0
            for j in range(self.num_branches):
                if i == j:
                    y += x[j]
                else:
                    y += self.fuse_layers[i][j](x[j])
            x_fuse.append(self.relu(y))
        return x_fuse


@mmcv.jit(derivate=True, coderize=True)
def varifocal_loss(pred,
                   target,
                   weight=None,
                   alpha=0.75,
                   gamma=2.0,
                   iou_weighted=True,
                   reduction='mean',
                   avg_factor=None):
    """`Varifocal Loss <https://arxiv.org/abs/2008.13367>`_

    Args:
        pred (torch.Tensor): The prediction with shape (N, C), C is the
            number of classes
        target (torch.Tensor): The learning target of the iou-aware
            classification score with shape (N, C), C is the number of classes.
        weight (torch.Tensor, optional): The weight of loss for each
            prediction. Defaults to None.
        alpha (float, optional): A balance factor for the negative part of
            Varifocal Loss, which is different from the alpha of Focal Loss.
            Defaults to 0.75.
        gamma (float, optional): The gamma for calculating the modulating
            factor. Defaults to 2.0.
        iou_weighted (bool, optional): Whether to weight the loss of the
            positive example with the iou target. Defaults to True.
        reduction (str, optional): The method used to reduce the loss into
            a scalar. Defaults to 'mean'. Options are "none", "mean" and
            "sum".
        avg_factor (int, optional): Average factor that is used to average
            the loss. Defaults to None.
    """
    # pred and target should be of the same size
    assert pred.size() == target.size()
    pred_sigmoid = pred.sigmoid()
    target = target.type_as(pred)
    if iou_weighted:
        focal_weight = target * (target > 0.0).float() + \
            alpha * (pred_sigmoid - target).abs().pow(gamma) * \
            (target <= 0.0).float()
    else:
        focal_weight = (target > 0.0).float() + \
            alpha * (pred_sigmoid - target).abs().pow(gamma) * \
            (target <= 0.0).float()
    loss = F.binary_cross_entropy_with_logits(
        pred, target, reduction='none') * focal_weight
    loss = weight_reduce_loss(loss, weight, reduction, avg_factor)
    return loss


@staticmethod
    def get_people_manager():
        """
        Method that returns the current people manager.
        """
        return PeopleManager()


def _convert_old_conf(console: Console, path: Path) -> str:
    """Reads old config file and converts it to the v2 toml."""
    cp = ConfigParser()
    cp.read_string(path.read_text())
    if not cp.has_section("default"):
        console.print(f"The config file {path!s} does not contain any configuration, nothing to migrate.")
        sys.exit(1)

    v1_config = dict(cp.items("default"))
    v2_config = v1_to_v2_config_dict(v1_config, env=False, get_config=False)
    v2_config_toml = tomli_w.dumps(v2_config)
    console.print(
        Markdown(f"Your v1 project config converted to the v2 format looks like this:\n```toml\n{v2_config_toml}\n```"),
    )
    return v2_config_toml


def _resize_seg(self, results):
        """Resize semantic segmentation map with ``results['scale']``."""
        for key in results.get('seg_fields', []):
            if self.keep_ratio:
                gt_seg = mmcv.imrescale(
                    results[key],
                    results['scale'],
                    interpolation='nearest',
                    backend=self.backend)
            else:
                gt_seg = mmcv.imresize(
                    results[key],
                    results['scale'],
                    interpolation='nearest',
                    backend=self.backend)
            results[key] = gt_seg


def simple_test(self, img, img_metas, rescale=False):
        """Test function without test time augmentation.

        Args:
            imgs (list[torch.Tensor]): List of multiple images
            img_metas (list[dict]): List of image information.
            rescale (bool, optional): Whether to rescale the results.
                Defaults to False.

        Returns:
            list[np.ndarray]: proposals
        """
        x = self.extract_feat(img)
        # get origin input shape to onnx dynamic input shape
        if torch.onnx.is_in_onnx_export():
            img_shape = torch._shape_as_tensor(img)[2:]
            img_metas[0]['img_shape_for_onnx'] = img_shape
        proposal_list = self.rpn_head.simple_test_rpn(x, img_metas)
        if rescale:
            for proposals, meta in zip(proposal_list, img_metas):
                proposals[:, :4] /= proposals.new_tensor(meta['scale_factor'])
        if torch.onnx.is_in_onnx_export():
            return proposal_list

        return [proposal.cpu().numpy() for proposal in proposal_list]


@staticmethod
    def __get_site(data):
        """
        查询单个站点信息
        """
        tid = data.get("id")
        site_free = False
        site_2xfree = False
        site_hr = False
        if tid:
            ret = Sites().get_sites(siteid=tid)
            if ret.get("signurl"):
                site_attr = SiteConf().get_grap_conf(ret.get("signurl"))
                if site_attr.get("FREE"):
                    site_free = True
                if site_attr.get("2XFREE"):
                    site_2xfree = True
                if site_attr.get("HR"):
                    site_hr = True
        else:
            ret = []
        return {"code": 0, "site": ret, "site_free": site_free, "site_2xfree": site_2xfree, "site_hr": site_hr}

"""
        查询单个站点信息
        """


def del_dataset(self, dataset_id, dataset_name):
        """
        考虑做伪删除，但是感觉没必要

        """
        msg_box = QMessageBox()  # 后悔药（不
        msg_box.setWindowTitle("提示")
        msg_box.setText(f"确认删除数据集 {dataset_name} 吗？\n{dataset_name} 将会永久失去!(真的很久!)")
        msg_box.setIcon(QMessageBox.Question)

        # 添加按钮
        yes_button = msg_box.addButton("确定", QMessageBox.AcceptRole)
        no_button = msg_box.addButton("取消", QMessageBox.RejectRole)

        # 显示消息框，等待用户响应
        msg_box.exec()

        # 获取用户的响应
        button_clicked = msg_box.clickedButton()
        if button_clicked == yes_button:
            try:
                # dataset = Dataset.delete().where(Dataset.dataset_id == dataset_id)
                # self.add_dataset_data()
                dataset = Dataset.get(Dataset.dataset_id == dataset_id)
                name = dataset.dataset_name
                dataset.delete_instance()
                del_file_by_dataset_id(dataset_id)

            except Exception as e:
                guilogger.error(f"删除数据集 id={dataset_id} 失败")
                guilogger.error(e)
            else:
                guilogger.info(f"数据集 {name} 成功删除")
            finally:
                self.add_dataset_data()

        else:
            pass

"""
        考虑做伪删除，但是感觉没必要

        """


def quat2euler(q, order='xyz', degrees=True):
    """
    Convert (w, x, y, z) quaternions to xyz euler angles. This is  used for bvh output.
    """
    q0 = q[..., 0]
    q1 = q[..., 1]
    q2 = q[..., 2]
    q3 = q[..., 3]
    es = torch.empty(q0.shape + (3,), device=q.device, dtype=q.dtype)

    if order == 'xyz':
        es[..., 2] = torch.atan2(2 * (q0 * q3 - q1 * q2), q0 * q0 + q1 * q1 - q2 * q2 - q3 * q3)
        es[..., 1] = torch.asin((2 * (q1 * q3 + q0 * q2)).clip(-1, 1))
        es[..., 0] = torch.atan2(2 * (q0 * q1 - q2 * q3), q0 * q0 - q1 * q1 - q2 * q2 + q3 * q3)
    else:
        raise NotImplementedError('Cannot convert to ordering %s' % order)

    if degrees:
        es = es * 180 / np.pi

    return es


def test_get_printer(self):
        """Tests the get_printer method."""
        self.assertIsInstance(PrinterFactory.get_printer("plain"), PlainPrinter)
        self.assertIsInstance(PrinterFactory.get_printer("markdown"), MarkdownPrinter)


def _utils_ToFloat(s):
  """Returns float(s) if s is a float. Otherwise None.

  Disallows infinities and nans.

  Args:
    s: A string to convert to a float.

  Returns:
    An float or None.
  """
  try:
    x = float(s)
    if x not in [float('inf'), float('-inf')] and x == x:  # not NaN
      return x
    else:
      return None
  except ValueError:
    return None


def check_file_path(file_path: Path):
    """
    Ensure file extension is in ALLOWED_FILE_TYPES or is a URL.
    If file ends with _translated.txt or _bilingual.txt, skip it.
    If there is any txt file ending with _translated.txt or _bilingual.txt, skip it.
    """
    if not file_path.suffix.lower() in ALLOWED_FILE_TYPES and not str(
            file_path).startswith('http'):
        print(f"File extension {file_path.suffix} is not allowed.")
        raise Exception("Please use a txt file or URL")

    if file_path.stem.endswith("_translated") or file_path.stem.endswith(
            "extracted_translated"):
        print(
            f"You already have a translated file for {file_path}, skipping...")
        return False
    elif file_path.stem.endswith("_bilingual") or file_path.stem.endswith(
            "extracted_bilingual"):
        print(
            f"You already have a bilingual file for {file_path}, skipping...")
        return False

    if (file_path.with_name(f"{file_path.stem}_translated.txt").exists() or
            file_path.with_name(f"{file_path.stem}_extracted_translated.txt").exists()):
        print(
            f"You already have a translated file for {file_path}, skipping...")
        return False

    return True


def get_proposal_pos_embed(self,
                               proposals,
                               num_pos_feats=128,
                               temperature=10000):
        """Get the position embedding of proposal."""
        scale = 2 * math.pi
        dim_t = torch.arange(
            num_pos_feats, dtype=torch.float32, device=proposals.device)
        dim_t = temperature**(2 * (dim_t // 2) / num_pos_feats)
        # N, L, 4
        proposals = proposals.sigmoid() * scale
        # N, L, 4, 128
        pos = proposals[:, :, :, None] / dim_t
        # N, L, 4, 64, 2
        pos = torch.stack((pos[:, :, :, 0::2].sin(), pos[:, :, :, 1::2].cos()),
                          dim=4).flatten(2)
        return pos


def get_reference_points(H, W, Z=8, num_points_in_pillar=4, dim='3d', bs=1, device='cpu', dtype=torch.float):
    """Get the reference points used in image cross-attention and single plane self-attention.
    Args:
        H, W: spatial shape of tpv.
        Z: hight of pillar.
        D: sample D points uniformly from each pillar.
        device (obj:`device`): The device where
            reference_points should be.
    Returns:
        Tensor: reference points used in decoder, has \
            shape (bs, num_keys, num_levels, 2).
    """

    # reference points in 3D space, used in image cross-attention
    if dim == '3d':
        zs = torch.linspace(0.5, Z - 0.5, num_points_in_pillar, dtype=dtype,
                            device=device).view(-1, 1, 1).expand(num_points_in_pillar, H, W) / Z
        xs = torch.linspace(0.5, W - 0.5, W, dtype=dtype,
                            device=device).view(1, 1, -1).expand(num_points_in_pillar, H, W) / W
        ys = torch.linspace(0.5, H - 0.5, H, dtype=dtype,
                            device=device).view(1, -1, 1).expand(num_points_in_pillar, H, W) / H
        ref_3d = torch.stack((xs, ys, zs), -1)
        ref_3d = ref_3d.permute(0, 3, 1, 2).flatten(2).permute(0, 2, 1)
        ref_3d = ref_3d[None].repeat(bs, 1, 1, 1)
        return ref_3d

    # reference points on 2D tpv plane, used in self attention in tpvformer04
    # which is an older version. Now we use get_cross_view_ref_points instead.
    elif dim == '2d':
        ref_y, ref_x = torch.meshgrid(
            torch.linspace(
                0.5, H - 0.5, H, dtype=dtype, device=device),
            torch.linspace(
                0.5, W - 0.5, W, dtype=dtype, device=device))
        ref_y = ref_y.reshape(-1)[None] / H
        ref_x = ref_x.reshape(-1)[None] / W
        ref_2d = torch.stack((ref_x, ref_y), -1)
        ref_2d = ref_2d.repeat(bs, 1, 1).unsqueeze(2)
        return ref_2d


def get_default(key):
    """Get default value for key"""
    return DEFAULTS.get(key)


@classmethod
  def version_9(
      cls, node: onnx_node.OnnxNode, inputs: Sequence[Any]
  ) -> Callable[..., Any]:
    """ONNX version_9 BatchNormalization op."""
    cls._prepare(node, inputs, onnx_batchnormalization)
    return onnx_batchnormalization


@classmethod
  def version_13(
      cls, node: onnx_node.OnnxNode, inputs: Sequence[Any]
  ) -> Callable[..., Any]:
    """ONNX version_13 Mul op."""
    cls._prepare(node, inputs, onnx_mul)
    return onnx_mul


def generate_markdown_documentation(
    pydantic_models: list[type[BaseModel]], model_prefix="Model", fields_prefix="Fields",
    documentation_with_field_description=True
) -> str:
    """
    Generate markdown documentation for a list of Pydantic models.

    Args:
        pydantic_models (list[type[BaseModel]]): list of Pydantic model classes.
        model_prefix (str): Prefix for the model section.
        fields_prefix (str): Prefix for the fields section.
        documentation_with_field_description (bool): Include field descriptions in the documentation.

    Returns:
        str: Generated text documentation.
    """
    documentation = ""
    pyd_models: list[tuple[type[BaseModel], bool]] = [(model, True) for model in pydantic_models]
    for model, add_prefix in pyd_models:
        if add_prefix:
            documentation += f"{model_prefix}: {model.__name__}\n"
        else:
            documentation += f"Model: {model.__name__}\n"

        # Handling multi-line model description with proper indentation

        class_doc = getdoc(model)
        base_class_doc = getdoc(BaseModel)
        class_description = class_doc if class_doc and class_doc != base_class_doc else ""
        if class_description != "":
            documentation += "  Description: "
            documentation += format_multiline_description(class_description, 0) + "\n"

        if add_prefix:
            # Indenting the fields section
            documentation += f"  {fields_prefix}:\n"
        else:
            documentation += f"  Fields:\n"  # noqa: F541
        if isclass(model) and issubclass(model, BaseModel):
            for name, field_type in get_type_hints(model).items():
                # if name == "markdown_code_block":
                #    continue
                if get_origin(field_type) == list:
                    element_type = get_args(field_type)[0]
                    if isclass(element_type) and issubclass(element_type, BaseModel):
                        pyd_models.append((element_type, False))
                if get_origin(field_type) == Union:
                    element_types = get_args(field_type)
                    for element_type in element_types:
                        if isclass(element_type) and issubclass(element_type, BaseModel):
                            pyd_models.append((element_type, False))
                documentation += generate_field_markdown(
                    name, field_type, model, documentation_with_field_description=documentation_with_field_description
                )
            documentation += "\n"

        if hasattr(model, "Config") and hasattr(model.Config,
                                                "json_schema_extra") and "example" in model.Config.json_schema_extra:
            documentation += f"  Expected Example Output for {format_model_and_field_name(model.__name__)}:\n"
            json_example = json.dumps(model.Config.json_schema_extra["example"])
            documentation += format_multiline_description(json_example, 2) + "\n"

    return documentation


@classmethod
    def templatable(cls: type[Button]) -> set[str]:
        """Return if an attribute is templatable, which is if the type-annotation is str."""
        schema = cls.schema()
        properties = schema["properties"]
        return {k for k, v in properties.items() if v["allow_template"]}


@property
    def stream(self) -> bool:
        r"""Returns whether the model supports streaming. But Groq API does
        not support streaming.
        """
        return False


def clean_cache():
    """
    清空搜索缓存
    """
    search_image_by_text_path_time.cache_clear()
    search_image_by_image.cache_clear()
    search_video_by_image.cache_clear()
    search_video_by_text_path_time.cache_clear()
    search_pexels_video_by_text.cache_clear()

"""
    清空搜索缓存
    """


def __validate_time_delta(value: str) -> str:
    """
    Check to see if passed string is in the list of possible Time Deltas.
    :param value: Time Delta name.
    :return: Passed value or No Return
    """
    valid_values = TIME_DELTA_VALUES
    if value in valid_values:
        return value
    else:
        logging.error(
            f"Invalid time_delta value: {value}.  Valid options: {valid_values}"
        )


def intree_extensions(
    paths: Iterable[str], package_dir: Optional[Dict[str, str]] = None
) -> List[Pybind11Extension]:
    """
    Generate Pybind11Extensions from source files directly located in a Python
    source tree.

    ``package_dir`` behaves as in ``setuptools.setup``.  If unset, the Python
    package root parent is determined as the first parent directory that does
    not contain an ``__init__.py`` file.
    """
    exts = []

    if package_dir is None:
        for path in paths:
            parent, _ = os.path.split(path)
            while os.path.exists(os.path.join(parent, "__init__.py")):
                parent, _ = os.path.split(parent)
            relname, _ = os.path.splitext(os.path.relpath(path, parent))
            qualified_name = relname.replace(os.path.sep, ".")
            exts.append(Pybind11Extension(qualified_name, [path]))
        return exts

    for path in paths:
        for prefix, parent in package_dir.items():
            if path.startswith(parent):
                relname, _ = os.path.splitext(os.path.relpath(path, parent))
                qualified_name = relname.replace(os.path.sep, ".")
                if prefix:
                    qualified_name = prefix + "." + qualified_name
                exts.append(Pybind11Extension(qualified_name, [path]))
                break
        else:
            msg = (
                f"path {path} is not a child of any of the directories listed "
                f"in 'package_dir' ({package_dir})"
            )
            raise ValueError(msg)

    return exts


def update_sys_path(path_to_add: str) -> None:
    """Add given path to `sys.path`."""
    if path_to_add not in sys.path and os.path.isdir(path_to_add):
        sys.path.append(path_to_add)