Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

forbid float weights for int storage for #289 #346

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 13 additions & 8 deletions src/boost_histogram/_internal/hist.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,11 @@ def __init__(self, *axes, **kwargs):

# Keyword only trick (change when Python2 is dropped)
with KWArgs(kwargs) as k:
storage = k.optional("storage", Double())
self._storage = k.optional("storage", Double())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can access the storage type from the C++ object, which is better than trying to hang on to it in Python.


# Check for missed parenthesis or incorrect types
if not isinstance(storage, Storage):
if issubclass(storage, Storage):
if not isinstance(self._storage, Storage):
if issubclass(self._storage, Storage):
raise KeyError(
"Passing in an initialized storage has been removed. Please add ()."
)
Expand All @@ -119,8 +119,8 @@ def __init__(self, *axes, **kwargs):

# Check all available histograms, and if the storage matches, return that one
for h in _histograms:
if isinstance(storage, h._storage_type):
self._hist = h(axes, storage)
if isinstance(self._storage, h._storage_type):
self._hist = h(axes, self._storage)
return

raise TypeError("Unsupported storage")
Expand Down Expand Up @@ -195,9 +195,14 @@ def fill(self, *args, **kwargs):
threaded filling. Using 0 will automatically pick the number of
available threads (usually two per core).
"""

# should not allow float weight for int storage
if "weight" in kwargs:
for w in kwargs["weight"]:
if not isinstance(self._storage._PyType, type(w)):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an incorrect check; weight could be a single value or an array of values, this is only checking for one int rather than an array (I think).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting, it does work on arrays of ints? Something like this might fix the other PR.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You might misunderstand. As you can see, for w in kwargs["weight"]: will iterate every value in weight list. And you can see the demo above in my comments. Every possible broken case is considered.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, okay. I see the loop. Does this work when this is not an array? And this will be horribly slow, since it's a Python loop.

Copy link
Collaborator Author

@LovelyBuggies LovelyBuggies Mar 28, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You get the point! Only weight=[1] is supported now. weight=1 is not supported. But it would not be a hard job if you really want!

And this will be horribly slow, since it's a Python loop

Yep, I have seen the importance to deep into the underlying C++ parts.

raise TypeError("Weight type must match storage type.")

threads = kwargs.pop("threads", None)

if threads is None or threads == 1:
self._hist.fill(*args, **kwargs)
else:
Expand All @@ -208,7 +213,7 @@ def fill(self, *args, **kwargs):
self._hist._storage_type is _core.storage.mean
or self._hist._storage_type is _core.storage.weighted_mean
):
raise RuntimeError("Mean histograms do not support threaded filling")
raise RuntimeError("Mean histograms do not support threaded filling.")

weight = kwargs.pop("weight", None)
sample = kwargs.pop("sample", None)
Expand Down
4 changes: 4 additions & 0 deletions src/boost_histogram/_internal/storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ def __repr__(self):
@set_family(MAIN_FAMILY)
@set_module("boost_histogram.storage")
class Int64(store.int64, Storage):
def __init__(self):
self._PyType = int()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is causing the segfault in the CI, as Int64 is not properly initializing store.int64 (but could be wrong). The fact the tests are segfaulting is slightly bothering me.

pass


Expand All @@ -29,6 +31,8 @@ class Double(store.double, Storage):
@set_family(MAIN_FAMILY)
@set_module("boost_histogram.storage")
class AtomicInt64(store.atomic_int64, Storage):
def __init__(self):
self._PyType = int()
pass


Expand Down