def METHOD_NAME(qnode, max_expansion=None, expansion_strategy=None):
    """Resource information about a quantum circuit.
    This transform converts a QNode into a callable that provides resource information
    about the circuit.
    Args:
        qnode (.QNode): the QNode to calculate the specifications for
    Keyword Args:
        max_expansion (int): The number of times the internal circuit should be expanded when
            calculating the specification. Defaults to ``qnode.max_expansion``.
        expansion_strategy (str): The strategy to use when circuit expansions or decompositions
            are required.
            - ``gradient``: The QNode will attempt to decompose
              the internal circuit such that all circuit operations are supported by the gradient
              method.
            - ``device``: The QNode will attempt to decompose the internal circuit
              such that all circuit operations are natively supported by the device.
    Returns:
        A function that has the same argument signature as ``qnode``. This function
        returns a dictionary of information about qnode structure.
    **Example**
    .. code-block:: python3
        x = np.array([0.1, 0.2])
        dev = qml.device('default.qubit', wires=2)
        @qml.qnode(dev, diff_method="parameter-shift", shifts=np.pi / 4)
        def circuit(x, add_ry=True):
            qml.RX(x[0], wires=0)
            qml.CNOT(wires=(0,1))
            if add_ry:
                qml.RY(x[1], wires=1)
            return qml.probs(wires=(0,1))
    >>> qml.specs(circuit)(x, add_ry=False)
    {'resources': Resources(num_wires=2, num_gates=2, gate_types=defaultdict(<class 'int'>, {'RX': 1, 'CNOT': 1}),
    gate_sizes=defaultdict(int, {1: 1, 2: 1}), depth=2, shots=Shots(total_shots=None, shot_vector=())),
    'gate_sizes': defaultdict(int, {1: 1, 2: 1}),
    'gate_types': defaultdict(int, {'RX': 1, 'CNOT': 1}),
    'num_operations': 2,
    'num_observables': 1,
    'num_diagonalizing_gates': 0,
    'num_used_wires': 2,
    'num_trainable_params': 1,
    'depth': 2,
    'num_device_wires': 2,
    'device_name': 'default.qubit',
    'expansion_strategy': 'gradient',
    'gradient_options': {'shifts': 0.7853981633974483},
    'interface': 'auto',
    'diff_method': 'parameter-shift',
    'gradient_fn': 'pennylane.gradients.parameter_shift.param_shift',
    'num_gradient_executions': 2}
    """
    def specs_qnode(*args, **kwargs):
        """Returns information on the structure and makeup of provided QNode.
        Dictionary keys:
            * ``"num_operations"`` number of operations in the qnode
            * ``"num_observables"`` number of observables in the qnode
            * ``"num_diagonalizing_gates"`` number of diagonalizing gates required for execution of the qnode
            * ``"resources"``: a :class:`~.resource.Resources` object containing resource quantities used by the qnode
            * ``"num_used_wires"``: number of wires used by the circuit
            * ``"num_device_wires"``: number of wires in device
            * ``"depth"``: longest path in directed acyclic graph representation
            * ``"device_name"``: name of QNode device
            * ``"expansion_strategy"``: string specifying method for decomposing operations in the circuit
            * ``"gradient_options"``: additional configurations for gradient computations
            * ``"interface"``: autodiff framework to dispatch to for the qnode execution
            * ``"diff_method"``: a string specifying the differntiation method
            * ``"gradient_fn"``: executable to compute the gradient of the qnode
        Potential Additional Information:
            * ``"num_trainable_params"``: number of individual scalars that are trainable
            * ``"num_gradient_executions"``: number of times circuit will execute when
                    calculating the derivative
        Returns:
            dict[str, Union[defaultdict,int]]: dictionaries that contain QNode specifications
        """
        initial_max_expansion = qnode.max_expansion
        initial_expansion_strategy = getattr(qnode, "expansion_strategy", None)
        try:
            qnode.max_expansion = initial_max_expansion if max_expansion is None else max_expansion
            qnode.expansion_strategy = expansion_strategy or initial_expansion_strategy
            qnode.construct(args, kwargs)
        finally:
            qnode.max_expansion = initial_max_expansion
            qnode.expansion_strategy = initial_expansion_strategy
        info = qnode.qtape.METHOD_NAME.copy()
        info["num_device_wires"] = qnode.device.num_wires
        info["device_name"] = qnode.device.short_name
        info["expansion_strategy"] = qnode.expansion_strategy
        info["gradient_options"] = qnode.gradient_kwargs
        info["interface"] = qnode.interface
        info["diff_method"] = (
            _get_absolute_import_path(qnode.diff_method)
            if callable(qnode.diff_method)
            else qnode.diff_method
        )
        if isinstance(qnode.gradient_fn, qml.gradients.gradient_transform):
            info["gradient_fn"] = _get_absolute_import_path(qnode.gradient_fn)
            try:
                info["num_gradient_executions"] = len(qnode.gradient_fn(qnode.qtape)[0])
            except Exception as e:  # pylint: disable=broad-except
                # In the case of a broad exception, we don't want the `qml.specs` transform
                # to fail. Instead, we simply indicate that the number of gradient executions
                # is not supported for the reason specified.
                info["num_gradient_executions"] = f"NotSupported: {str(e)}"
        else:
            info["gradient_fn"] = qnode.gradient_fn
        return info
    return specs_qnode