Try to converge on internal types consistency. - #574

Closed
Carreau wants to merge 1 commit into
zarr-developers:masterfrom
Carreau:converge-types
Closed

Try to converge on internal types consistency.#574
Carreau wants to merge 1 commit into
zarr-developers:masterfrom
Carreau:converge-types

Conversation

@Carreau

Copy link
Copy Markdown
Contributor

While it is convenient for user on high level API to be able to pass
arround many types (array, bytes, or even dictionary, list, strings),
It can make it relatively hard to follow internally if the types are not
consistant.

In particular this can relatively complicate weaving the v3 spec into
the core of Zarr and add a number of conditional if we are not sure of
the type we get.

This try to be a little more consistent in what the implementation
emits right now this try to make sure that all the core only try to
converge toward bytes, so that store users can expect to alway get bytes
back from Zarr-Python stores, and as much as possible give bytes back,
and mostly affects the ConsolidatedMetadataStore which used to – unlike
other store – return objects instead of bytes, as well as the tests
directly testing the stores.

We of course can't be too strict as some existing store may have stored
some values as not-bytes (pickle), and we still want to support this for
the time being,but with this changes, we can add many assert isinstance(x, bytes_like) in many places ans still have the test suite
to pass.

In particular in all the decode/encode metadata functions, and Group
class.

One extra change in test is the removal of an old conditional import of
h5py in the test suite which is unnecessary since introduction of the
pytest's importorskip for h5py tests.

[Description of PR]

TODO:

  • Add unit tests and/or doctests in docstrings
  • Add docstrings and API docs for any new/modified user-facing classes and functions
  • New/modified features documented in docs/tutorial.rst
  • Changes documented in docs/release.rst
  • AppVeyor and Travis CI passes
  • Test coverage is 100% (Coveralls passes)

While it is convenient for user on high level API to be able to pass
arround many types (array, bytes, or even dictionary, list, strings),
It can make it relatively hard to follow internally if the types are not
consistant.
In particular this can relatively complicate weaving the v3 spec into
the core of Zarr and add a number of conditional if we are not sure of
the type we get.
This try to be a little more consistent in what the implementation
_emits_ right now this try to make sure that all the core only try to
converge toward bytes, so that store users can expect to alway get bytes
back from Zarr-Python stores, and as much as possible give bytes back,
and mostly affects the ConsolidatedMetadataStore which used to – unlike
other store – return objects instead of bytes, as well as the tests
directly testing the stores.
We of course can't be too strict as some existing store may have stored
some values as not-bytes (pickle), and we still want to support this for
the time being,but with this changes, we can add many `assert
isinstance(x, bytes_like)` in many places ans still have the test suite
to pass.
In particular in all the decode/encode metadata functions, and Group
class.
One extra change in test is the removal of an old conditional import of
h5py in the test suite which is unnecessary since introduction of the
pytest's `importorskip` for h5py tests.
@Carreau

Copy link
Copy Markdown
ContributorAuthor

Extra notes, returning object with Consolidated metadata mean that you actually get reference to mutable objects and have a risk of modifying the internal state of the consolidated store if you don't pay attention.

Would it be ok in a separate PR to add a "strict" mode (opt-in), that would trigger a bunch of assert isinstance(xxx, bytes_likes) or similar in a couple of places to help with type stability ?

@jakirkham

Copy link
Copy Markdown
Member

Sorry for not raising this yesterday. I'm a bit unsure about this as we have uses cases where we would like to handle other non-bytes objects like mmap ( #377 ) and CuPy ndarrays ( zarr-developers/numcodecs#212 ) ( #501 ).

@Carreau

Copy link
Copy Markdown
ContributorAuthor

I think it would be ok to ensure only bytes-like in python. My main problem is to poke at it to figure out whether it's already decoded or not.

@alimanfooalimanfoo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Hi @Carreau, in general agree with spirit of trying to achieve type consistency, but a couple of points worth some discussion here.

Comment threadzarr/core.py

# encode and store
cdata = self._encode_chunk(chunk)
cdata = ensure_bytes(self._encode_chunk(chunk))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

N.B., ensuring bytes may introduce a memory copy, which may be unnecessary. Memory copies can noticeably affect performance. Ensuring we have something that supports the buffer interface would be better.

Comment threadzarr/storage.py
Comment on lines +2514 to +2516
self.meta_store = {}
for k, v in meta["metadata"].items():
self.meta_store[k] = json_dumps(v)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

FWIW this was originally how this worked, but this introduces an extra unnecessary JSON encode/decode round trip into the processing of consolidated metadata. In practice that may not be a performance issue, but it seemed awkward to have this extra JSON encode/decode if it wasn't necessary. Hence I introduced a special case which avoided the necessity for this, see the parse_metadata function in the original PR.

@Carreau
Carreau marked this pull request as draft September 9, 2020 17:13
@joshmoore

Copy link
Copy Markdown
Member

I assume this is now handled by #898et al. cc: @grlee77

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@Carreau@jakirkham@joshmoore@alimanfoo
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Try to converge on internal types consistency. - #574

Closed
Carreau wants to merge 1 commit into
zarr-developers:masterfrom
Carreau:converge-types
Closed

Try to converge on internal types consistency.#574
Carreau wants to merge 1 commit into
zarr-developers:masterfrom
Carreau:converge-types

Conversation

@Carreau

Copy link
Copy Markdown
Contributor

While it is convenient for user on high level API to be able to pass
arround many types (array, bytes, or even dictionary, list, strings),
It can make it relatively hard to follow internally if the types are not
consistant.

In particular this can relatively complicate weaving the v3 spec into
the core of Zarr and add a number of conditional if we are not sure of
the type we get.

This try to be a little more consistent in what the implementation
emits right now this try to make sure that all the core only try to
converge toward bytes, so that store users can expect to alway get bytes
back from Zarr-Python stores, and as much as possible give bytes back,
and mostly affects the ConsolidatedMetadataStore which used to – unlike
other store – return objects instead of bytes, as well as the tests
directly testing the stores.

We of course can't be too strict as some existing store may have stored
some values as not-bytes (pickle), and we still want to support this for
the time being,but with this changes, we can add many assert isinstance(x, bytes_like) in many places ans still have the test suite
to pass.

In particular in all the decode/encode metadata functions, and Group
class.

One extra change in test is the removal of an old conditional import of
h5py in the test suite which is unnecessary since introduction of the
pytest's importorskip for h5py tests.

[Description of PR]

TODO:

  • Add unit tests and/or doctests in docstrings
  • Add docstrings and API docs for any new/modified user-facing classes and functions
  • New/modified features documented in docs/tutorial.rst
  • Changes documented in docs/release.rst
  • AppVeyor and Travis CI passes
  • Test coverage is 100% (Coveralls passes)

While it is convenient for user on high level API to be able to pass
arround many types (array, bytes, or even dictionary, list, strings),
It can make it relatively hard to follow internally if the types are not
consistant.
In particular this can relatively complicate weaving the v3 spec into
the core of Zarr and add a number of conditional if we are not sure of
the type we get.
This try to be a little more consistent in what the implementation
_emits_ right now this try to make sure that all the core only try to
converge toward bytes, so that store users can expect to alway get bytes
back from Zarr-Python stores, and as much as possible give bytes back,
and mostly affects the ConsolidatedMetadataStore which used to – unlike
other store – return objects instead of bytes, as well as the tests
directly testing the stores.
We of course can't be too strict as some existing store may have stored
some values as not-bytes (pickle), and we still want to support this for
the time being,but with this changes, we can add many `assert
isinstance(x, bytes_like)` in many places ans still have the test suite
to pass.
In particular in all the decode/encode metadata functions, and Group
class.
One extra change in test is the removal of an old conditional import of
h5py in the test suite which is unnecessary since introduction of the
pytest's `importorskip` for h5py tests.
@Carreau

Copy link
Copy Markdown
ContributorAuthor

Extra notes, returning object with Consolidated metadata mean that you actually get reference to mutable objects and have a risk of modifying the internal state of the consolidated store if you don't pay attention.

Would it be ok in a separate PR to add a "strict" mode (opt-in), that would trigger a bunch of assert isinstance(xxx, bytes_likes) or similar in a couple of places to help with type stability ?

@jakirkham

Copy link
Copy Markdown
Member

Sorry for not raising this yesterday. I'm a bit unsure about this as we have uses cases where we would like to handle other non-bytes objects like mmap ( #377 ) and CuPy ndarrays ( zarr-developers/numcodecs#212 ) ( #501 ).

@Carreau

Copy link
Copy Markdown
ContributorAuthor

I think it would be ok to ensure only bytes-like in python. My main problem is to poke at it to figure out whether it's already decoded or not.

@alimanfooalimanfoo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Hi @Carreau, in general agree with spirit of trying to achieve type consistency, but a couple of points worth some discussion here.

Comment threadzarr/core.py

# encode and store
cdata = self._encode_chunk(chunk)
cdata = ensure_bytes(self._encode_chunk(chunk))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

N.B., ensuring bytes may introduce a memory copy, which may be unnecessary. Memory copies can noticeably affect performance. Ensuring we have something that supports the buffer interface would be better.

Comment threadzarr/storage.py
Comment on lines +2514 to +2516
self.meta_store = {}
for k, v in meta["metadata"].items():
self.meta_store[k] = json_dumps(v)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

FWIW this was originally how this worked, but this introduces an extra unnecessary JSON encode/decode round trip into the processing of consolidated metadata. In practice that may not be a performance issue, but it seemed awkward to have this extra JSON encode/decode if it wasn't necessary. Hence I introduced a special case which avoided the necessity for this, see the parse_metadata function in the original PR.

@Carreau
Carreau marked this pull request as draft September 9, 2020 17:13
@joshmoore

Copy link
Copy Markdown
Member

I assume this is now handled by #898et al. cc: @grlee77

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@Carreau@jakirkham@joshmoore@alimanfoo
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Try to converge on internal types consistency. - #574

Closed
Carreau wants to merge 1 commit into
zarr-developers:masterfrom
Carreau:converge-types
Closed

Try to converge on internal types consistency.#574
Carreau wants to merge 1 commit into
zarr-developers:masterfrom
Carreau:converge-types

Conversation

@Carreau

Copy link
Copy Markdown
Contributor

While it is convenient for user on high level API to be able to pass
arround many types (array, bytes, or even dictionary, list, strings),
It can make it relatively hard to follow internally if the types are not
consistant.

In particular this can relatively complicate weaving the v3 spec into
the core of Zarr and add a number of conditional if we are not sure of
the type we get.

This try to be a little more consistent in what the implementation
emits right now this try to make sure that all the core only try to
converge toward bytes, so that store users can expect to alway get bytes
back from Zarr-Python stores, and as much as possible give bytes back,
and mostly affects the ConsolidatedMetadataStore which used to – unlike
other store – return objects instead of bytes, as well as the tests
directly testing the stores.

We of course can't be too strict as some existing store may have stored
some values as not-bytes (pickle), and we still want to support this for
the time being,but with this changes, we can add many assert isinstance(x, bytes_like) in many places ans still have the test suite
to pass.

In particular in all the decode/encode metadata functions, and Group
class.

One extra change in test is the removal of an old conditional import of
h5py in the test suite which is unnecessary since introduction of the
pytest's importorskip for h5py tests.

[Description of PR]

TODO:

  • Add unit tests and/or doctests in docstrings
  • Add docstrings and API docs for any new/modified user-facing classes and functions
  • New/modified features documented in docs/tutorial.rst
  • Changes documented in docs/release.rst
  • AppVeyor and Travis CI passes
  • Test coverage is 100% (Coveralls passes)

While it is convenient for user on high level API to be able to pass
arround many types (array, bytes, or even dictionary, list, strings),
It can make it relatively hard to follow internally if the types are not
consistant.
In particular this can relatively complicate weaving the v3 spec into
the core of Zarr and add a number of conditional if we are not sure of
the type we get.
This try to be a little more consistent in what the implementation
_emits_ right now this try to make sure that all the core only try to
converge toward bytes, so that store users can expect to alway get bytes
back from Zarr-Python stores, and as much as possible give bytes back,
and mostly affects the ConsolidatedMetadataStore which used to – unlike
other store – return objects instead of bytes, as well as the tests
directly testing the stores.
We of course can't be too strict as some existing store may have stored
some values as not-bytes (pickle), and we still want to support this for
the time being,but with this changes, we can add many `assert
isinstance(x, bytes_like)` in many places ans still have the test suite
to pass.
In particular in all the decode/encode metadata functions, and Group
class.
One extra change in test is the removal of an old conditional import of
h5py in the test suite which is unnecessary since introduction of the
pytest's `importorskip` for h5py tests.
@Carreau

Copy link
Copy Markdown
ContributorAuthor

Extra notes, returning object with Consolidated metadata mean that you actually get reference to mutable objects and have a risk of modifying the internal state of the consolidated store if you don't pay attention.

Would it be ok in a separate PR to add a "strict" mode (opt-in), that would trigger a bunch of assert isinstance(xxx, bytes_likes) or similar in a couple of places to help with type stability ?

@jakirkham

Copy link
Copy Markdown
Member

Sorry for not raising this yesterday. I'm a bit unsure about this as we have uses cases where we would like to handle other non-bytes objects like mmap ( #377 ) and CuPy ndarrays ( zarr-developers/numcodecs#212 ) ( #501 ).

@Carreau

Copy link
Copy Markdown
ContributorAuthor

I think it would be ok to ensure only bytes-like in python. My main problem is to poke at it to figure out whether it's already decoded or not.

@alimanfooalimanfoo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Hi @Carreau, in general agree with spirit of trying to achieve type consistency, but a couple of points worth some discussion here.

Comment threadzarr/core.py

# encode and store
cdata = self._encode_chunk(chunk)
cdata = ensure_bytes(self._encode_chunk(chunk))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

N.B., ensuring bytes may introduce a memory copy, which may be unnecessary. Memory copies can noticeably affect performance. Ensuring we have something that supports the buffer interface would be better.

Comment threadzarr/storage.py
Comment on lines +2514 to +2516
self.meta_store = {}
for k, v in meta["metadata"].items():
self.meta_store[k] = json_dumps(v)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

FWIW this was originally how this worked, but this introduces an extra unnecessary JSON encode/decode round trip into the processing of consolidated metadata. In practice that may not be a performance issue, but it seemed awkward to have this extra JSON encode/decode if it wasn't necessary. Hence I introduced a special case which avoided the necessity for this, see the parse_metadata function in the original PR.

@Carreau
Carreau marked this pull request as draft September 9, 2020 17:13
@joshmoore

Copy link
Copy Markdown
Member

I assume this is now handled by #898et al. cc: @grlee77

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@Carreau@jakirkham@joshmoore@alimanfoo
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Try to converge on internal types consistency. - #574

Closed
Carreau wants to merge 1 commit into
zarr-developers:masterfrom
Carreau:converge-types
Closed

Try to converge on internal types consistency.#574
Carreau wants to merge 1 commit into
zarr-developers:masterfrom
Carreau:converge-types

Conversation

@Carreau

Copy link
Copy Markdown
Contributor

While it is convenient for user on high level API to be able to pass
arround many types (array, bytes, or even dictionary, list, strings),
It can make it relatively hard to follow internally if the types are not
consistant.

In particular this can relatively complicate weaving the v3 spec into
the core of Zarr and add a number of conditional if we are not sure of
the type we get.

This try to be a little more consistent in what the implementation
emits right now this try to make sure that all the core only try to
converge toward bytes, so that store users can expect to alway get bytes
back from Zarr-Python stores, and as much as possible give bytes back,
and mostly affects the ConsolidatedMetadataStore which used to – unlike
other store – return objects instead of bytes, as well as the tests
directly testing the stores.

We of course can't be too strict as some existing store may have stored
some values as not-bytes (pickle), and we still want to support this for
the time being,but with this changes, we can add many assert isinstance(x, bytes_like) in many places ans still have the test suite
to pass.

In particular in all the decode/encode metadata functions, and Group
class.

One extra change in test is the removal of an old conditional import of
h5py in the test suite which is unnecessary since introduction of the
pytest's importorskip for h5py tests.

[Description of PR]

TODO:

  • Add unit tests and/or doctests in docstrings
  • Add docstrings and API docs for any new/modified user-facing classes and functions
  • New/modified features documented in docs/tutorial.rst
  • Changes documented in docs/release.rst
  • AppVeyor and Travis CI passes
  • Test coverage is 100% (Coveralls passes)

While it is convenient for user on high level API to be able to pass
arround many types (array, bytes, or even dictionary, list, strings),
It can make it relatively hard to follow internally if the types are not
consistant.
In particular this can relatively complicate weaving the v3 spec into
the core of Zarr and add a number of conditional if we are not sure of
the type we get.
This try to be a little more consistent in what the implementation
_emits_ right now this try to make sure that all the core only try to
converge toward bytes, so that store users can expect to alway get bytes
back from Zarr-Python stores, and as much as possible give bytes back,
and mostly affects the ConsolidatedMetadataStore which used to – unlike
other store – return objects instead of bytes, as well as the tests
directly testing the stores.
We of course can't be too strict as some existing store may have stored
some values as not-bytes (pickle), and we still want to support this for
the time being,but with this changes, we can add many `assert
isinstance(x, bytes_like)` in many places ans still have the test suite
to pass.
In particular in all the decode/encode metadata functions, and Group
class.
One extra change in test is the removal of an old conditional import of
h5py in the test suite which is unnecessary since introduction of the
pytest's `importorskip` for h5py tests.
@Carreau

Copy link
Copy Markdown
ContributorAuthor

Extra notes, returning object with Consolidated metadata mean that you actually get reference to mutable objects and have a risk of modifying the internal state of the consolidated store if you don't pay attention.

Would it be ok in a separate PR to add a "strict" mode (opt-in), that would trigger a bunch of assert isinstance(xxx, bytes_likes) or similar in a couple of places to help with type stability ?

@jakirkham

Copy link
Copy Markdown
Member

Sorry for not raising this yesterday. I'm a bit unsure about this as we have uses cases where we would like to handle other non-bytes objects like mmap ( #377 ) and CuPy ndarrays ( zarr-developers/numcodecs#212 ) ( #501 ).

@Carreau

Copy link
Copy Markdown
ContributorAuthor

I think it would be ok to ensure only bytes-like in python. My main problem is to poke at it to figure out whether it's already decoded or not.

@alimanfooalimanfoo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Hi @Carreau, in general agree with spirit of trying to achieve type consistency, but a couple of points worth some discussion here.

Comment threadzarr/core.py

# encode and store
cdata = self._encode_chunk(chunk)
cdata = ensure_bytes(self._encode_chunk(chunk))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

N.B., ensuring bytes may introduce a memory copy, which may be unnecessary. Memory copies can noticeably affect performance. Ensuring we have something that supports the buffer interface would be better.

Comment threadzarr/storage.py
Comment on lines +2514 to +2516
self.meta_store = {}
for k, v in meta["metadata"].items():
self.meta_store[k] = json_dumps(v)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

FWIW this was originally how this worked, but this introduces an extra unnecessary JSON encode/decode round trip into the processing of consolidated metadata. In practice that may not be a performance issue, but it seemed awkward to have this extra JSON encode/decode if it wasn't necessary. Hence I introduced a special case which avoided the necessity for this, see the parse_metadata function in the original PR.

@Carreau
Carreau marked this pull request as draft September 9, 2020 17:13
@joshmoore

Copy link
Copy Markdown
Member

I assume this is now handled by #898et al. cc: @grlee77

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@Carreau@jakirkham@joshmoore@alimanfoo
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Try to converge on internal types consistency. - #574

Closed
Carreau wants to merge 1 commit into
zarr-developers:masterfrom
Carreau:converge-types
Closed

Try to converge on internal types consistency.#574
Carreau wants to merge 1 commit into
zarr-developers:masterfrom
Carreau:converge-types

Conversation

@Carreau

Copy link
Copy Markdown
Contributor

While it is convenient for user on high level API to be able to pass
arround many types (array, bytes, or even dictionary, list, strings),
It can make it relatively hard to follow internally if the types are not
consistant.

In particular this can relatively complicate weaving the v3 spec into
the core of Zarr and add a number of conditional if we are not sure of
the type we get.

This try to be a little more consistent in what the implementation
emits right now this try to make sure that all the core only try to
converge toward bytes, so that store users can expect to alway get bytes
back from Zarr-Python stores, and as much as possible give bytes back,
and mostly affects the ConsolidatedMetadataStore which used to – unlike
other store – return objects instead of bytes, as well as the tests
directly testing the stores.

We of course can't be too strict as some existing store may have stored
some values as not-bytes (pickle), and we still want to support this for
the time being,but with this changes, we can add many assert isinstance(x, bytes_like) in many places ans still have the test suite
to pass.

In particular in all the decode/encode metadata functions, and Group
class.

One extra change in test is the removal of an old conditional import of
h5py in the test suite which is unnecessary since introduction of the
pytest's importorskip for h5py tests.

[Description of PR]

TODO:

  • Add unit tests and/or doctests in docstrings
  • Add docstrings and API docs for any new/modified user-facing classes and functions
  • New/modified features documented in docs/tutorial.rst
  • Changes documented in docs/release.rst
  • AppVeyor and Travis CI passes
  • Test coverage is 100% (Coveralls passes)

While it is convenient for user on high level API to be able to pass
arround many types (array, bytes, or even dictionary, list, strings),
It can make it relatively hard to follow internally if the types are not
consistant.
In particular this can relatively complicate weaving the v3 spec into
the core of Zarr and add a number of conditional if we are not sure of
the type we get.
This try to be a little more consistent in what the implementation
_emits_ right now this try to make sure that all the core only try to
converge toward bytes, so that store users can expect to alway get bytes
back from Zarr-Python stores, and as much as possible give bytes back,
and mostly affects the ConsolidatedMetadataStore which used to – unlike
other store – return objects instead of bytes, as well as the tests
directly testing the stores.
We of course can't be too strict as some existing store may have stored
some values as not-bytes (pickle), and we still want to support this for
the time being,but with this changes, we can add many `assert
isinstance(x, bytes_like)` in many places ans still have the test suite
to pass.
In particular in all the decode/encode metadata functions, and Group
class.
One extra change in test is the removal of an old conditional import of
h5py in the test suite which is unnecessary since introduction of the
pytest's `importorskip` for h5py tests.
@Carreau

Copy link
Copy Markdown
ContributorAuthor

Extra notes, returning object with Consolidated metadata mean that you actually get reference to mutable objects and have a risk of modifying the internal state of the consolidated store if you don't pay attention.

Would it be ok in a separate PR to add a "strict" mode (opt-in), that would trigger a bunch of assert isinstance(xxx, bytes_likes) or similar in a couple of places to help with type stability ?

@jakirkham

Copy link
Copy Markdown
Member

Sorry for not raising this yesterday. I'm a bit unsure about this as we have uses cases where we would like to handle other non-bytes objects like mmap ( #377 ) and CuPy ndarrays ( zarr-developers/numcodecs#212 ) ( #501 ).

@Carreau

Copy link
Copy Markdown
ContributorAuthor

I think it would be ok to ensure only bytes-like in python. My main problem is to poke at it to figure out whether it's already decoded or not.

@alimanfooalimanfoo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Hi @Carreau, in general agree with spirit of trying to achieve type consistency, but a couple of points worth some discussion here.

Comment threadzarr/core.py

# encode and store
cdata = self._encode_chunk(chunk)
cdata = ensure_bytes(self._encode_chunk(chunk))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

N.B., ensuring bytes may introduce a memory copy, which may be unnecessary. Memory copies can noticeably affect performance. Ensuring we have something that supports the buffer interface would be better.

Comment threadzarr/storage.py
Comment on lines +2514 to +2516
self.meta_store = {}
for k, v in meta["metadata"].items():
self.meta_store[k] = json_dumps(v)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

FWIW this was originally how this worked, but this introduces an extra unnecessary JSON encode/decode round trip into the processing of consolidated metadata. In practice that may not be a performance issue, but it seemed awkward to have this extra JSON encode/decode if it wasn't necessary. Hence I introduced a special case which avoided the necessity for this, see the parse_metadata function in the original PR.

@Carreau
Carreau marked this pull request as draft September 9, 2020 17:13
@joshmoore

Copy link
Copy Markdown
Member

I assume this is now handled by #898et al. cc: @grlee77

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@Carreau@jakirkham@joshmoore@alimanfoo
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Try to converge on internal types consistency. - #574

Closed
Carreau wants to merge 1 commit into
zarr-developers:masterfrom
Carreau:converge-types
Closed

Try to converge on internal types consistency.#574
Carreau wants to merge 1 commit into
zarr-developers:masterfrom
Carreau:converge-types

Conversation

@Carreau

Copy link
Copy Markdown
Contributor

While it is convenient for user on high level API to be able to pass
arround many types (array, bytes, or even dictionary, list, strings),
It can make it relatively hard to follow internally if the types are not
consistant.

In particular this can relatively complicate weaving the v3 spec into
the core of Zarr and add a number of conditional if we are not sure of
the type we get.

This try to be a little more consistent in what the implementation
emits right now this try to make sure that all the core only try to
converge toward bytes, so that store users can expect to alway get bytes
back from Zarr-Python stores, and as much as possible give bytes back,
and mostly affects the ConsolidatedMetadataStore which used to – unlike
other store – return objects instead of bytes, as well as the tests
directly testing the stores.

We of course can't be too strict as some existing store may have stored
some values as not-bytes (pickle), and we still want to support this for
the time being,but with this changes, we can add many assert isinstance(x, bytes_like) in many places ans still have the test suite
to pass.

In particular in all the decode/encode metadata functions, and Group
class.

One extra change in test is the removal of an old conditional import of
h5py in the test suite which is unnecessary since introduction of the
pytest's importorskip for h5py tests.

[Description of PR]

TODO:

  • Add unit tests and/or doctests in docstrings
  • Add docstrings and API docs for any new/modified user-facing classes and functions
  • New/modified features documented in docs/tutorial.rst
  • Changes documented in docs/release.rst
  • AppVeyor and Travis CI passes
  • Test coverage is 100% (Coveralls passes)

While it is convenient for user on high level API to be able to pass
arround many types (array, bytes, or even dictionary, list, strings),
It can make it relatively hard to follow internally if the types are not
consistant.
In particular this can relatively complicate weaving the v3 spec into
the core of Zarr and add a number of conditional if we are not sure of
the type we get.
This try to be a little more consistent in what the implementation
_emits_ right now this try to make sure that all the core only try to
converge toward bytes, so that store users can expect to alway get bytes
back from Zarr-Python stores, and as much as possible give bytes back,
and mostly affects the ConsolidatedMetadataStore which used to – unlike
other store – return objects instead of bytes, as well as the tests
directly testing the stores.
We of course can't be too strict as some existing store may have stored
some values as not-bytes (pickle), and we still want to support this for
the time being,but with this changes, we can add many `assert
isinstance(x, bytes_like)` in many places ans still have the test suite
to pass.
In particular in all the decode/encode metadata functions, and Group
class.
One extra change in test is the removal of an old conditional import of
h5py in the test suite which is unnecessary since introduction of the
pytest's `importorskip` for h5py tests.
@Carreau

Copy link
Copy Markdown
ContributorAuthor

Extra notes, returning object with Consolidated metadata mean that you actually get reference to mutable objects and have a risk of modifying the internal state of the consolidated store if you don't pay attention.

Would it be ok in a separate PR to add a "strict" mode (opt-in), that would trigger a bunch of assert isinstance(xxx, bytes_likes) or similar in a couple of places to help with type stability ?

@jakirkham

Copy link
Copy Markdown
Member

Sorry for not raising this yesterday. I'm a bit unsure about this as we have uses cases where we would like to handle other non-bytes objects like mmap ( #377 ) and CuPy ndarrays ( zarr-developers/numcodecs#212 ) ( #501 ).

@Carreau

Copy link
Copy Markdown
ContributorAuthor

I think it would be ok to ensure only bytes-like in python. My main problem is to poke at it to figure out whether it's already decoded or not.

@alimanfooalimanfoo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Hi @Carreau, in general agree with spirit of trying to achieve type consistency, but a couple of points worth some discussion here.

Comment threadzarr/core.py

# encode and store
cdata = self._encode_chunk(chunk)
cdata = ensure_bytes(self._encode_chunk(chunk))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

N.B., ensuring bytes may introduce a memory copy, which may be unnecessary. Memory copies can noticeably affect performance. Ensuring we have something that supports the buffer interface would be better.

Comment threadzarr/storage.py
Comment on lines +2514 to +2516
self.meta_store = {}
for k, v in meta["metadata"].items():
self.meta_store[k] = json_dumps(v)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

FWIW this was originally how this worked, but this introduces an extra unnecessary JSON encode/decode round trip into the processing of consolidated metadata. In practice that may not be a performance issue, but it seemed awkward to have this extra JSON encode/decode if it wasn't necessary. Hence I introduced a special case which avoided the necessity for this, see the parse_metadata function in the original PR.

@Carreau
Carreau marked this pull request as draft September 9, 2020 17:13
@joshmoore

Copy link
Copy Markdown
Member

I assume this is now handled by #898et al. cc: @grlee77

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@Carreau@jakirkham@joshmoore@alimanfoo
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Try to converge on internal types consistency. - #574

Closed
Carreau wants to merge 1 commit into
zarr-developers:masterfrom
Carreau:converge-types
Closed

Try to converge on internal types consistency.#574
Carreau wants to merge 1 commit into
zarr-developers:masterfrom
Carreau:converge-types

Conversation

@Carreau

Copy link
Copy Markdown
Contributor

While it is convenient for user on high level API to be able to pass
arround many types (array, bytes, or even dictionary, list, strings),
It can make it relatively hard to follow internally if the types are not
consistant.

In particular this can relatively complicate weaving the v3 spec into
the core of Zarr and add a number of conditional if we are not sure of
the type we get.

This try to be a little more consistent in what the implementation
emits right now this try to make sure that all the core only try to
converge toward bytes, so that store users can expect to alway get bytes
back from Zarr-Python stores, and as much as possible give bytes back,
and mostly affects the ConsolidatedMetadataStore which used to – unlike
other store – return objects instead of bytes, as well as the tests
directly testing the stores.

We of course can't be too strict as some existing store may have stored
some values as not-bytes (pickle), and we still want to support this for
the time being,but with this changes, we can add many assert isinstance(x, bytes_like) in many places ans still have the test suite
to pass.

In particular in all the decode/encode metadata functions, and Group
class.

One extra change in test is the removal of an old conditional import of
h5py in the test suite which is unnecessary since introduction of the
pytest's importorskip for h5py tests.

[Description of PR]

TODO:

  • Add unit tests and/or doctests in docstrings
  • Add docstrings and API docs for any new/modified user-facing classes and functions
  • New/modified features documented in docs/tutorial.rst
  • Changes documented in docs/release.rst
  • AppVeyor and Travis CI passes
  • Test coverage is 100% (Coveralls passes)

While it is convenient for user on high level API to be able to pass
arround many types (array, bytes, or even dictionary, list, strings),
It can make it relatively hard to follow internally if the types are not
consistant.
In particular this can relatively complicate weaving the v3 spec into
the core of Zarr and add a number of conditional if we are not sure of
the type we get.
This try to be a little more consistent in what the implementation
_emits_ right now this try to make sure that all the core only try to
converge toward bytes, so that store users can expect to alway get bytes
back from Zarr-Python stores, and as much as possible give bytes back,
and mostly affects the ConsolidatedMetadataStore which used to – unlike
other store – return objects instead of bytes, as well as the tests
directly testing the stores.
We of course can't be too strict as some existing store may have stored
some values as not-bytes (pickle), and we still want to support this for
the time being,but with this changes, we can add many `assert
isinstance(x, bytes_like)` in many places ans still have the test suite
to pass.
In particular in all the decode/encode metadata functions, and Group
class.
One extra change in test is the removal of an old conditional import of
h5py in the test suite which is unnecessary since introduction of the
pytest's `importorskip` for h5py tests.
@Carreau

Copy link
Copy Markdown
ContributorAuthor

Extra notes, returning object with Consolidated metadata mean that you actually get reference to mutable objects and have a risk of modifying the internal state of the consolidated store if you don't pay attention.

Would it be ok in a separate PR to add a "strict" mode (opt-in), that would trigger a bunch of assert isinstance(xxx, bytes_likes) or similar in a couple of places to help with type stability ?

@jakirkham

Copy link
Copy Markdown
Member

Sorry for not raising this yesterday. I'm a bit unsure about this as we have uses cases where we would like to handle other non-bytes objects like mmap ( #377 ) and CuPy ndarrays ( zarr-developers/numcodecs#212 ) ( #501 ).

@Carreau

Copy link
Copy Markdown
ContributorAuthor

I think it would be ok to ensure only bytes-like in python. My main problem is to poke at it to figure out whether it's already decoded or not.

@alimanfooalimanfoo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Hi @Carreau, in general agree with spirit of trying to achieve type consistency, but a couple of points worth some discussion here.

Comment threadzarr/core.py

# encode and store
cdata = self._encode_chunk(chunk)
cdata = ensure_bytes(self._encode_chunk(chunk))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

N.B., ensuring bytes may introduce a memory copy, which may be unnecessary. Memory copies can noticeably affect performance. Ensuring we have something that supports the buffer interface would be better.

Comment threadzarr/storage.py
Comment on lines +2514 to +2516
self.meta_store = {}
for k, v in meta["metadata"].items():
self.meta_store[k] = json_dumps(v)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

FWIW this was originally how this worked, but this introduces an extra unnecessary JSON encode/decode round trip into the processing of consolidated metadata. In practice that may not be a performance issue, but it seemed awkward to have this extra JSON encode/decode if it wasn't necessary. Hence I introduced a special case which avoided the necessity for this, see the parse_metadata function in the original PR.

@Carreau
Carreau marked this pull request as draft September 9, 2020 17:13
@joshmoore

Copy link
Copy Markdown
Member

I assume this is now handled by #898et al. cc: @grlee77

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@Carreau@jakirkham@joshmoore@alimanfoo
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Try to converge on internal types consistency. - #574

Closed
Carreau wants to merge 1 commit into
zarr-developers:masterfrom
Carreau:converge-types
Closed

Try to converge on internal types consistency.#574
Carreau wants to merge 1 commit into
zarr-developers:masterfrom
Carreau:converge-types

Conversation

@Carreau

Copy link
Copy Markdown
Contributor

While it is convenient for user on high level API to be able to pass
arround many types (array, bytes, or even dictionary, list, strings),
It can make it relatively hard to follow internally if the types are not
consistant.

In particular this can relatively complicate weaving the v3 spec into
the core of Zarr and add a number of conditional if we are not sure of
the type we get.

This try to be a little more consistent in what the implementation
emits right now this try to make sure that all the core only try to
converge toward bytes, so that store users can expect to alway get bytes
back from Zarr-Python stores, and as much as possible give bytes back,
and mostly affects the ConsolidatedMetadataStore which used to – unlike
other store – return objects instead of bytes, as well as the tests
directly testing the stores.

We of course can't be too strict as some existing store may have stored
some values as not-bytes (pickle), and we still want to support this for
the time being,but with this changes, we can add many assert isinstance(x, bytes_like) in many places ans still have the test suite
to pass.

In particular in all the decode/encode metadata functions, and Group
class.

One extra change in test is the removal of an old conditional import of
h5py in the test suite which is unnecessary since introduction of the
pytest's importorskip for h5py tests.

[Description of PR]

TODO:

  • Add unit tests and/or doctests in docstrings
  • Add docstrings and API docs for any new/modified user-facing classes and functions
  • New/modified features documented in docs/tutorial.rst
  • Changes documented in docs/release.rst
  • AppVeyor and Travis CI passes
  • Test coverage is 100% (Coveralls passes)

While it is convenient for user on high level API to be able to pass
arround many types (array, bytes, or even dictionary, list, strings),
It can make it relatively hard to follow internally if the types are not
consistant.
In particular this can relatively complicate weaving the v3 spec into
the core of Zarr and add a number of conditional if we are not sure of
the type we get.
This try to be a little more consistent in what the implementation
_emits_ right now this try to make sure that all the core only try to
converge toward bytes, so that store users can expect to alway get bytes
back from Zarr-Python stores, and as much as possible give bytes back,
and mostly affects the ConsolidatedMetadataStore which used to – unlike
other store – return objects instead of bytes, as well as the tests
directly testing the stores.
We of course can't be too strict as some existing store may have stored
some values as not-bytes (pickle), and we still want to support this for
the time being,but with this changes, we can add many `assert
isinstance(x, bytes_like)` in many places ans still have the test suite
to pass.
In particular in all the decode/encode metadata functions, and Group
class.
One extra change in test is the removal of an old conditional import of
h5py in the test suite which is unnecessary since introduction of the
pytest's `importorskip` for h5py tests.
@Carreau

Copy link
Copy Markdown
ContributorAuthor

Extra notes, returning object with Consolidated metadata mean that you actually get reference to mutable objects and have a risk of modifying the internal state of the consolidated store if you don't pay attention.

Would it be ok in a separate PR to add a "strict" mode (opt-in), that would trigger a bunch of assert isinstance(xxx, bytes_likes) or similar in a couple of places to help with type stability ?

@jakirkham

Copy link
Copy Markdown
Member

Sorry for not raising this yesterday. I'm a bit unsure about this as we have uses cases where we would like to handle other non-bytes objects like mmap ( #377 ) and CuPy ndarrays ( zarr-developers/numcodecs#212 ) ( #501 ).

@Carreau

Copy link
Copy Markdown
ContributorAuthor

I think it would be ok to ensure only bytes-like in python. My main problem is to poke at it to figure out whether it's already decoded or not.

@alimanfooalimanfoo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Hi @Carreau, in general agree with spirit of trying to achieve type consistency, but a couple of points worth some discussion here.

Comment threadzarr/core.py

# encode and store
cdata = self._encode_chunk(chunk)
cdata = ensure_bytes(self._encode_chunk(chunk))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

N.B., ensuring bytes may introduce a memory copy, which may be unnecessary. Memory copies can noticeably affect performance. Ensuring we have something that supports the buffer interface would be better.

Comment threadzarr/storage.py
Comment on lines +2514 to +2516
self.meta_store = {}
for k, v in meta["metadata"].items():
self.meta_store[k] = json_dumps(v)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

FWIW this was originally how this worked, but this introduces an extra unnecessary JSON encode/decode round trip into the processing of consolidated metadata. In practice that may not be a performance issue, but it seemed awkward to have this extra JSON encode/decode if it wasn't necessary. Hence I introduced a special case which avoided the necessity for this, see the parse_metadata function in the original PR.

@Carreau
Carreau marked this pull request as draft September 9, 2020 17:13
@joshmoore

Copy link
Copy Markdown
Member

I assume this is now handled by #898et al. cc: @grlee77

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@Carreau@jakirkham@joshmoore@alimanfoo