pybind / pybind/pybind11

Wrapping empty list works, wrapping empty set results in a TypeError

Open
#2,122 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
C++
Stars
18k
Forks
2.3k
Avg merge
5d 17h
Merged PRs (30d)
10

Description

Issue description

I am trying to wrap a C++ function which takes as input a set with pybind11. If the set is non-empty, wrapping works fine,
while if the set is empty I get errors such as

TypeError: print_set(): incompatible function arguments. The following argument types are supported:
    1. (arg0: Set[int]) -> None

I realize that the type int cannot be deduced from an empty set. However, wrapping of empty lists succeeds.
Is it possible to extend set conversion to the case of empty set?

Thanks.

Reproducible example code

import cppimport

def compile_module():
    cpp_code = """
    <%
    setup_pybind11(cfg)
    %>

    #include <pybind11/pybind11.h>
    #include <pybind11/stl.h>
    #include <iostream>

    void print_list(const std::vector<int> & list){
        std::cout << "List: ";
        for (auto& i: list) {
            std::cout << i << " ";
        }
        std::cout << std::endl;
    }

    void print_set(const std::set<int> & set){
        std::cout << "Set: ";
        for (auto& i: set) {
            std::cout << i << " ";
        }
        std::cout << std::endl;
    }

    void print_list_of_lists(const std::vector<std::vector<int>> & lists){
        std::cout << "Lists: ";
        for (auto & list: lists) {
            for (auto& i: list) {
                std::cout << i << " ";
            }
            std::cout << ", ";
        }
        std::cout << std::endl;
    }

    void print_list_of_sets(const std::vector<std::set<int>> & sets){
        std::cout << "Sets: ";
        for (auto & set: sets) {
            for (auto& i: set) {
                std::cout << i << " ";
            }
            std::cout << ", ";
        }
        std::cout << std::endl;
    }

    PYBIND11_MODULE(pybind_tester, m)
    {
      m.def("print_list", &print_list);
      m.def("print_set", &print_set);
      m.def("print_list_of_lists", &print_list_of_lists);
      m.def("print_list_of_sets", &print_list_of_sets);
    }
    """

    open("pybind_tester.cpp", "w").write(cpp_code)

    return cppimport.imp("pybind_tester")

module = compile_module()

# Print non-empty containers
module.print_list([8, 9])
module.print_set({1, 2})

# Print empty containers
module.print_list([])
try:
    module.print_set({})
except TypeError:
    print("Set: failure")
else:
    raise RuntimeError("Expecting failure")

# Print list of containers with all non-empty elements
module.print_list_of_lists([[8, 9], [1, 2, 3], [4]])
module.print_list_of_sets([{1, 2}, {6}, {4, 3}])

# Print list of containers with all non-empty elements
module.print_list_of_lists([[8, 9], [1, 2, 3], [4], []])
try:
    module.print_list_of_sets([{1, 2}, {6}, {4, 3}, {}])
except TypeError:
    print("Sets: failure")
else:
    raise RuntimeError("Expecting failure")

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by running the reproducible Python/C++ example and inspect the STL conversion path included through pybind11/stl.h, comparing empty list and empty set handling. Done means an empty set is accepted for a set[int] argument, including an empty nested set, without changing the existing non-empty behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp, python
Domain
api
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.