Create a Base store class for Zarr Store (update) - #789

Merged
joshmoore merged 39 commits into
zarr-developers:masterfrom
grlee77:base-store-v2
Oct 21, 2021
Merged

Create a Base store class for Zarr Store (update)#789
joshmoore merged 39 commits into
zarr-developers:masterfrom
grlee77:base-store-v2

Conversation

@grlee77

Copy link
Copy Markdown
Contributor

Use a base Store class instead of just MutableMapping

I am resuming the work @Carreau started in #612 here. This is mostly just a rebase of that PR with a small new commit in 8136713. Matthias and I met earlier today and we decided that starting with this PR should make it easier to add zarr-v3 support without trying to implement an entirely independent set of classes. The goal is to reduce code duplication between v2 and v3 where possible (None of the changes in this PR are specific to v3 yet)

Note that I updated the version string text to 2.9.0 in a couple of places, but that may need to be updated again depending on when this is merged.

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
  • GitHub Actions have all passed
  • Test coverage is 100% (Codecov passes)

@pep8speaks

pep8speaks commented Jun 23, 2021

Copy link
Copy Markdown

Hello @grlee77! Thanks for updating this PR. We checked the lines you've touched for PEP 8 issues, and found:

There are currently no PEP 8 issues detected in this Pull Request. Cheers! 🍻

Comment last updated at 2021-10-21 04:50:40 UTC

@joshmoore

Copy link
Copy Markdown
Member

The Fatal Python error: Segmentation fault was also seen in #788 (comment)

@grlee77

grlee77 commented Jun 24, 2021

Copy link
Copy Markdown
ContributorAuthor

Yes, I just started looking into it. I can reproduce it locally after upgrading to NumPy 1.21. It does not occur for NumPy 1.20.3

@grlee77

Copy link
Copy Markdown
ContributorAuthor

I opened numpy/numpy#19325 regarding this segfault

@codecov

codecovBot commented Jun 24, 2021

Copy link
Copy Markdown

Codecov Report

Merging #789 (06086dc) into master (d8ac8a7) will increase coverage by 0.00%.
The diff coverage is 100.00%.

@@ Coverage Diff @@## master #789 +/- ##
=======================================
Coverage 99.94% 99.94% =======================================
Files 31 32 +1 Lines 11133 11175 +42 =======================================
+ Hits 11127 11169 +42 
Misses 6 6 
Impacted FilesCoverage Δ
zarr/_storage/absstore.py100.00% <100.00%> (ø)
zarr/_storage/store.py100.00% <100.00%> (ø)
zarr/attrs.py100.00% <100.00%> (ø)
zarr/convenience.py100.00% <100.00%> (ø)
zarr/core.py100.00% <100.00%> (ø)
zarr/creation.py100.00% <100.00%> (ø)
zarr/hierarchy.py100.00% <100.00%> (ø)
zarr/storage.py100.00% <100.00%> (ø)
zarr/tests/test_attrs.py100.00% <100.00%> (ø)
zarr/tests/test_convenience.py100.00% <100.00%> (ø)
... and 7 more

@grlee77grlee77 mentioned this pull request Jun 24, 2021
6 tasks
@jakirkham

Copy link
Copy Markdown
Member

cc @martindurant@rabernat@jhamman@shoyer@shikharsg (in case any of you have thoughts here 🙂 this will affect how other store implementations work 😉)

@jakirkham

Copy link
Copy Markdown
Member

Also cc @TomAugspurger 🙂

@grlee77

Copy link
Copy Markdown
ContributorAuthor

Looking ahead to adding v3 spec support:

In terms of class members for a Store interface, the v3 spec indicates the following should be present:

  • readable stores must have: get
  • writeable stores must have : set, erase, erase_prefix
  • listable stores should have one or more of: list, list_dir, list_prefix:

The Store class here matches the existing store implementations in zarr-python in that it has a listdir method, but this differs from the list_dir spelling in the v3 spec which is unfortunate. erase seems equivalent to __delitem__ while erase_prefix seems equivalent to rmdir

@joshmoore

Copy link
Copy Markdown
Member

Green now except for the removed build (==1.16.4) which can be ignored.

@martindurant

Copy link
Copy Markdown
Member

Clarification: if we open an array or group, and pass a dict-like as before, it gets wrapped to become a Store, right?

@joshmoorejoshmoore 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.

As mentioned on call, this is looking good. Thanks, @grlee77. Probably the most important remaining step is to get the release blurb so that we can all agree on the degree of breakage and have a comprehensive list of what (if anything) will no longer take dicts. Additionally some documentation may be necessary around the "pass by reference" semantics.

Propose then to target this for a 2.11

@joshmoore

Copy link
Copy Markdown
Member

Solved the (minor) merge conflict, @grlee77. From my side, I'd say let's try to get this into a RC as early as tomorrow. (Or someone else can do it this evening. I'm going to 🛏️ ) Up to you if you think we should also try to get metadata handling in.

(Release blurb would still be appreciated.)

@grlee77

Copy link
Copy Markdown
ContributorAuthor

Solved the (minor) merge conflict, @grlee77. From my side, I'd say let's try to get this into a RC as early as tomorrow. (Or someone else can do it this evening. I'm going to bed ) Up to you if you think we should also try to get metadata handling in.

I think we may as well also merge the metadata handling for the RC. Let's discuss in the community call.

One remaining doubt about the approach here is the presence of listdir and rmdir methods in this class which seems specific to our current v2 store implementations. They are not among the abstract store methods listed in the v3 spec (there is a list_dir, not listdir but behavior is not exactly the same. erase_prefix in the spec is like rmdir). I am wondering if we should instead hava a BaseStore that does not have these methods and then use a StoreV2 subclass that would add these?

A future StoreV3 class could then inherit from BaseStore instead of StoreV2, so that it would not have to inherit additional methods that are not part of the spec. That said, at the moment many high-level functions use listdir and rmdir, so we may want to keep them around, at least temporarily.

BaseStore does not have the listdir or rmdir methods
cleaned up some type declerations, making sure mypy passes
Otherwise the save_array doc example fails to write to a ZipStore
Comment threadzarr/storage.py
`Store` interface."""
path = normalize_storage_path(path)
if hasattr(store, "rmdir"):
if hasattr(store, "rmdir") and store.is_erasable(): # type: ignore

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.

Not a blocker for getting this into a 2.11 alpha build but is the hasattr not now redundant?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Not quite yet. There are calls to rmdir from _init_array_metadata (via init_array which still allows a MutableMapping for the store). This is why I put store as StoreLike in the type annotation, but then I had to add "# type: ignore" on this line or mypy complained that MutableMappings do not have an is_erasable attribute.

@joshmoore

Copy link
Copy Markdown
Member

As discussed during the community call yesterday evening (my time), merging this into a 2.11 alpha release with the (now passing) proposed changes.

Thanks to both @grlee77 and @Carreau for all their labors! 👏🏽

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.

6 participants

@grlee77@pep8speaks@joshmoore@jakirkham@martindurant@Carreau
, '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

Create a Base store class for Zarr Store (update) - #789

Merged
joshmoore merged 39 commits into
zarr-developers:masterfrom
grlee77:base-store-v2
Oct 21, 2021
Merged

Create a Base store class for Zarr Store (update)#789
joshmoore merged 39 commits into
zarr-developers:masterfrom
grlee77:base-store-v2

Conversation

@grlee77

Copy link
Copy Markdown
Contributor

Use a base Store class instead of just MutableMapping

I am resuming the work @Carreau started in #612 here. This is mostly just a rebase of that PR with a small new commit in 8136713. Matthias and I met earlier today and we decided that starting with this PR should make it easier to add zarr-v3 support without trying to implement an entirely independent set of classes. The goal is to reduce code duplication between v2 and v3 where possible (None of the changes in this PR are specific to v3 yet)

Note that I updated the version string text to 2.9.0 in a couple of places, but that may need to be updated again depending on when this is merged.

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
  • GitHub Actions have all passed
  • Test coverage is 100% (Codecov passes)

@pep8speaks

pep8speaks commented Jun 23, 2021

Copy link
Copy Markdown

Hello @grlee77! Thanks for updating this PR. We checked the lines you've touched for PEP 8 issues, and found:

There are currently no PEP 8 issues detected in this Pull Request. Cheers! 🍻

Comment last updated at 2021-10-21 04:50:40 UTC

@joshmoore

Copy link
Copy Markdown
Member

The Fatal Python error: Segmentation fault was also seen in #788 (comment)

@grlee77

grlee77 commented Jun 24, 2021

Copy link
Copy Markdown
ContributorAuthor

Yes, I just started looking into it. I can reproduce it locally after upgrading to NumPy 1.21. It does not occur for NumPy 1.20.3

@grlee77

Copy link
Copy Markdown
ContributorAuthor

I opened numpy/numpy#19325 regarding this segfault

@codecov

codecovBot commented Jun 24, 2021

Copy link
Copy Markdown

Codecov Report

Merging #789 (06086dc) into master (d8ac8a7) will increase coverage by 0.00%.
The diff coverage is 100.00%.

@@ Coverage Diff @@## master #789 +/- ##
=======================================
Coverage 99.94% 99.94% =======================================
Files 31 32 +1 Lines 11133 11175 +42 =======================================
+ Hits 11127 11169 +42 
Misses 6 6 
Impacted FilesCoverage Δ
zarr/_storage/absstore.py100.00% <100.00%> (ø)
zarr/_storage/store.py100.00% <100.00%> (ø)
zarr/attrs.py100.00% <100.00%> (ø)
zarr/convenience.py100.00% <100.00%> (ø)
zarr/core.py100.00% <100.00%> (ø)
zarr/creation.py100.00% <100.00%> (ø)
zarr/hierarchy.py100.00% <100.00%> (ø)
zarr/storage.py100.00% <100.00%> (ø)
zarr/tests/test_attrs.py100.00% <100.00%> (ø)
zarr/tests/test_convenience.py100.00% <100.00%> (ø)
... and 7 more

@grlee77grlee77 mentioned this pull request Jun 24, 2021
6 tasks
@jakirkham

Copy link
Copy Markdown
Member

cc @martindurant@rabernat@jhamman@shoyer@shikharsg (in case any of you have thoughts here 🙂 this will affect how other store implementations work 😉)

@jakirkham

Copy link
Copy Markdown
Member

Also cc @TomAugspurger 🙂

@grlee77

Copy link
Copy Markdown
ContributorAuthor

Looking ahead to adding v3 spec support:

In terms of class members for a Store interface, the v3 spec indicates the following should be present:

  • readable stores must have: get
  • writeable stores must have : set, erase, erase_prefix
  • listable stores should have one or more of: list, list_dir, list_prefix:

The Store class here matches the existing store implementations in zarr-python in that it has a listdir method, but this differs from the list_dir spelling in the v3 spec which is unfortunate. erase seems equivalent to __delitem__ while erase_prefix seems equivalent to rmdir

@joshmoore

Copy link
Copy Markdown
Member

Green now except for the removed build (==1.16.4) which can be ignored.

@martindurant

Copy link
Copy Markdown
Member

Clarification: if we open an array or group, and pass a dict-like as before, it gets wrapped to become a Store, right?

@joshmoorejoshmoore 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.

As mentioned on call, this is looking good. Thanks, @grlee77. Probably the most important remaining step is to get the release blurb so that we can all agree on the degree of breakage and have a comprehensive list of what (if anything) will no longer take dicts. Additionally some documentation may be necessary around the "pass by reference" semantics.

Propose then to target this for a 2.11

@joshmoore

Copy link
Copy Markdown
Member

Solved the (minor) merge conflict, @grlee77. From my side, I'd say let's try to get this into a RC as early as tomorrow. (Or someone else can do it this evening. I'm going to 🛏️ ) Up to you if you think we should also try to get metadata handling in.

(Release blurb would still be appreciated.)

@grlee77

Copy link
Copy Markdown
ContributorAuthor

Solved the (minor) merge conflict, @grlee77. From my side, I'd say let's try to get this into a RC as early as tomorrow. (Or someone else can do it this evening. I'm going to bed ) Up to you if you think we should also try to get metadata handling in.

I think we may as well also merge the metadata handling for the RC. Let's discuss in the community call.

One remaining doubt about the approach here is the presence of listdir and rmdir methods in this class which seems specific to our current v2 store implementations. They are not among the abstract store methods listed in the v3 spec (there is a list_dir, not listdir but behavior is not exactly the same. erase_prefix in the spec is like rmdir). I am wondering if we should instead hava a BaseStore that does not have these methods and then use a StoreV2 subclass that would add these?

A future StoreV3 class could then inherit from BaseStore instead of StoreV2, so that it would not have to inherit additional methods that are not part of the spec. That said, at the moment many high-level functions use listdir and rmdir, so we may want to keep them around, at least temporarily.

BaseStore does not have the listdir or rmdir methods
cleaned up some type declerations, making sure mypy passes
Otherwise the save_array doc example fails to write to a ZipStore
Comment threadzarr/storage.py
`Store` interface."""
path = normalize_storage_path(path)
if hasattr(store, "rmdir"):
if hasattr(store, "rmdir") and store.is_erasable(): # type: ignore

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.

Not a blocker for getting this into a 2.11 alpha build but is the hasattr not now redundant?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Not quite yet. There are calls to rmdir from _init_array_metadata (via init_array which still allows a MutableMapping for the store). This is why I put store as StoreLike in the type annotation, but then I had to add "# type: ignore" on this line or mypy complained that MutableMappings do not have an is_erasable attribute.

@joshmoore

Copy link
Copy Markdown
Member

As discussed during the community call yesterday evening (my time), merging this into a 2.11 alpha release with the (now passing) proposed changes.

Thanks to both @grlee77 and @Carreau for all their labors! 👏🏽

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.

6 participants

@grlee77@pep8speaks@joshmoore@jakirkham@martindurant@Carreau
, '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

Create a Base store class for Zarr Store (update) - #789

Merged
joshmoore merged 39 commits into
zarr-developers:masterfrom
grlee77:base-store-v2
Oct 21, 2021
Merged

Create a Base store class for Zarr Store (update)#789
joshmoore merged 39 commits into
zarr-developers:masterfrom
grlee77:base-store-v2

Conversation

@grlee77

Copy link
Copy Markdown
Contributor

Use a base Store class instead of just MutableMapping

I am resuming the work @Carreau started in #612 here. This is mostly just a rebase of that PR with a small new commit in 8136713. Matthias and I met earlier today and we decided that starting with this PR should make it easier to add zarr-v3 support without trying to implement an entirely independent set of classes. The goal is to reduce code duplication between v2 and v3 where possible (None of the changes in this PR are specific to v3 yet)

Note that I updated the version string text to 2.9.0 in a couple of places, but that may need to be updated again depending on when this is merged.

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
  • GitHub Actions have all passed
  • Test coverage is 100% (Codecov passes)

@pep8speaks

pep8speaks commented Jun 23, 2021

Copy link
Copy Markdown

Hello @grlee77! Thanks for updating this PR. We checked the lines you've touched for PEP 8 issues, and found:

There are currently no PEP 8 issues detected in this Pull Request. Cheers! 🍻

Comment last updated at 2021-10-21 04:50:40 UTC

@joshmoore

Copy link
Copy Markdown
Member

The Fatal Python error: Segmentation fault was also seen in #788 (comment)

@grlee77

grlee77 commented Jun 24, 2021

Copy link
Copy Markdown
ContributorAuthor

Yes, I just started looking into it. I can reproduce it locally after upgrading to NumPy 1.21. It does not occur for NumPy 1.20.3

@grlee77

Copy link
Copy Markdown
ContributorAuthor

I opened numpy/numpy#19325 regarding this segfault

@codecov

codecovBot commented Jun 24, 2021

Copy link
Copy Markdown

Codecov Report

Merging #789 (06086dc) into master (d8ac8a7) will increase coverage by 0.00%.
The diff coverage is 100.00%.

@@ Coverage Diff @@## master #789 +/- ##
=======================================
Coverage 99.94% 99.94% =======================================
Files 31 32 +1 Lines 11133 11175 +42 =======================================
+ Hits 11127 11169 +42 
Misses 6 6 
Impacted FilesCoverage Δ
zarr/_storage/absstore.py100.00% <100.00%> (ø)
zarr/_storage/store.py100.00% <100.00%> (ø)
zarr/attrs.py100.00% <100.00%> (ø)
zarr/convenience.py100.00% <100.00%> (ø)
zarr/core.py100.00% <100.00%> (ø)
zarr/creation.py100.00% <100.00%> (ø)
zarr/hierarchy.py100.00% <100.00%> (ø)
zarr/storage.py100.00% <100.00%> (ø)
zarr/tests/test_attrs.py100.00% <100.00%> (ø)
zarr/tests/test_convenience.py100.00% <100.00%> (ø)
... and 7 more

@grlee77grlee77 mentioned this pull request Jun 24, 2021
6 tasks
@jakirkham

Copy link
Copy Markdown
Member

cc @martindurant@rabernat@jhamman@shoyer@shikharsg (in case any of you have thoughts here 🙂 this will affect how other store implementations work 😉)

@jakirkham

Copy link
Copy Markdown
Member

Also cc @TomAugspurger 🙂

@grlee77

Copy link
Copy Markdown
ContributorAuthor

Looking ahead to adding v3 spec support:

In terms of class members for a Store interface, the v3 spec indicates the following should be present:

  • readable stores must have: get
  • writeable stores must have : set, erase, erase_prefix
  • listable stores should have one or more of: list, list_dir, list_prefix:

The Store class here matches the existing store implementations in zarr-python in that it has a listdir method, but this differs from the list_dir spelling in the v3 spec which is unfortunate. erase seems equivalent to __delitem__ while erase_prefix seems equivalent to rmdir

@joshmoore

Copy link
Copy Markdown
Member

Green now except for the removed build (==1.16.4) which can be ignored.

@martindurant

Copy link
Copy Markdown
Member

Clarification: if we open an array or group, and pass a dict-like as before, it gets wrapped to become a Store, right?

@joshmoorejoshmoore 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.

As mentioned on call, this is looking good. Thanks, @grlee77. Probably the most important remaining step is to get the release blurb so that we can all agree on the degree of breakage and have a comprehensive list of what (if anything) will no longer take dicts. Additionally some documentation may be necessary around the "pass by reference" semantics.

Propose then to target this for a 2.11

@joshmoore

Copy link
Copy Markdown
Member

Solved the (minor) merge conflict, @grlee77. From my side, I'd say let's try to get this into a RC as early as tomorrow. (Or someone else can do it this evening. I'm going to 🛏️ ) Up to you if you think we should also try to get metadata handling in.

(Release blurb would still be appreciated.)

@grlee77

Copy link
Copy Markdown
ContributorAuthor

Solved the (minor) merge conflict, @grlee77. From my side, I'd say let's try to get this into a RC as early as tomorrow. (Or someone else can do it this evening. I'm going to bed ) Up to you if you think we should also try to get metadata handling in.

I think we may as well also merge the metadata handling for the RC. Let's discuss in the community call.

One remaining doubt about the approach here is the presence of listdir and rmdir methods in this class which seems specific to our current v2 store implementations. They are not among the abstract store methods listed in the v3 spec (there is a list_dir, not listdir but behavior is not exactly the same. erase_prefix in the spec is like rmdir). I am wondering if we should instead hava a BaseStore that does not have these methods and then use a StoreV2 subclass that would add these?

A future StoreV3 class could then inherit from BaseStore instead of StoreV2, so that it would not have to inherit additional methods that are not part of the spec. That said, at the moment many high-level functions use listdir and rmdir, so we may want to keep them around, at least temporarily.

BaseStore does not have the listdir or rmdir methods
cleaned up some type declerations, making sure mypy passes
Otherwise the save_array doc example fails to write to a ZipStore
Comment threadzarr/storage.py
`Store` interface."""
path = normalize_storage_path(path)
if hasattr(store, "rmdir"):
if hasattr(store, "rmdir") and store.is_erasable(): # type: ignore

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.

Not a blocker for getting this into a 2.11 alpha build but is the hasattr not now redundant?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Not quite yet. There are calls to rmdir from _init_array_metadata (via init_array which still allows a MutableMapping for the store). This is why I put store as StoreLike in the type annotation, but then I had to add "# type: ignore" on this line or mypy complained that MutableMappings do not have an is_erasable attribute.

@joshmoore

Copy link
Copy Markdown
Member

As discussed during the community call yesterday evening (my time), merging this into a 2.11 alpha release with the (now passing) proposed changes.

Thanks to both @grlee77 and @Carreau for all their labors! 👏🏽

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.

6 participants

@grlee77@pep8speaks@joshmoore@jakirkham@martindurant@Carreau
, '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

Create a Base store class for Zarr Store (update) - #789

Merged
joshmoore merged 39 commits into
zarr-developers:masterfrom
grlee77:base-store-v2
Oct 21, 2021
Merged

Create a Base store class for Zarr Store (update)#789
joshmoore merged 39 commits into
zarr-developers:masterfrom
grlee77:base-store-v2

Conversation

@grlee77

Copy link
Copy Markdown
Contributor

Use a base Store class instead of just MutableMapping

I am resuming the work @Carreau started in #612 here. This is mostly just a rebase of that PR with a small new commit in 8136713. Matthias and I met earlier today and we decided that starting with this PR should make it easier to add zarr-v3 support without trying to implement an entirely independent set of classes. The goal is to reduce code duplication between v2 and v3 where possible (None of the changes in this PR are specific to v3 yet)

Note that I updated the version string text to 2.9.0 in a couple of places, but that may need to be updated again depending on when this is merged.

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
  • GitHub Actions have all passed
  • Test coverage is 100% (Codecov passes)

@pep8speaks

pep8speaks commented Jun 23, 2021

Copy link
Copy Markdown

Hello @grlee77! Thanks for updating this PR. We checked the lines you've touched for PEP 8 issues, and found:

There are currently no PEP 8 issues detected in this Pull Request. Cheers! 🍻

Comment last updated at 2021-10-21 04:50:40 UTC

@joshmoore

Copy link
Copy Markdown
Member

The Fatal Python error: Segmentation fault was also seen in #788 (comment)

@grlee77

grlee77 commented Jun 24, 2021

Copy link
Copy Markdown
ContributorAuthor

Yes, I just started looking into it. I can reproduce it locally after upgrading to NumPy 1.21. It does not occur for NumPy 1.20.3

@grlee77

Copy link
Copy Markdown
ContributorAuthor

I opened numpy/numpy#19325 regarding this segfault

@codecov

codecovBot commented Jun 24, 2021

Copy link
Copy Markdown

Codecov Report

Merging #789 (06086dc) into master (d8ac8a7) will increase coverage by 0.00%.
The diff coverage is 100.00%.

@@ Coverage Diff @@## master #789 +/- ##
=======================================
Coverage 99.94% 99.94% =======================================
Files 31 32 +1 Lines 11133 11175 +42 =======================================
+ Hits 11127 11169 +42 
Misses 6 6 
Impacted FilesCoverage Δ
zarr/_storage/absstore.py100.00% <100.00%> (ø)
zarr/_storage/store.py100.00% <100.00%> (ø)
zarr/attrs.py100.00% <100.00%> (ø)
zarr/convenience.py100.00% <100.00%> (ø)
zarr/core.py100.00% <100.00%> (ø)
zarr/creation.py100.00% <100.00%> (ø)
zarr/hierarchy.py100.00% <100.00%> (ø)
zarr/storage.py100.00% <100.00%> (ø)
zarr/tests/test_attrs.py100.00% <100.00%> (ø)
zarr/tests/test_convenience.py100.00% <100.00%> (ø)
... and 7 more

@grlee77grlee77 mentioned this pull request Jun 24, 2021
6 tasks
@jakirkham

Copy link
Copy Markdown
Member

cc @martindurant@rabernat@jhamman@shoyer@shikharsg (in case any of you have thoughts here 🙂 this will affect how other store implementations work 😉)

@jakirkham

Copy link
Copy Markdown
Member

Also cc @TomAugspurger 🙂

@grlee77

Copy link
Copy Markdown
ContributorAuthor

Looking ahead to adding v3 spec support:

In terms of class members for a Store interface, the v3 spec indicates the following should be present:

  • readable stores must have: get
  • writeable stores must have : set, erase, erase_prefix
  • listable stores should have one or more of: list, list_dir, list_prefix:

The Store class here matches the existing store implementations in zarr-python in that it has a listdir method, but this differs from the list_dir spelling in the v3 spec which is unfortunate. erase seems equivalent to __delitem__ while erase_prefix seems equivalent to rmdir

@joshmoore

Copy link
Copy Markdown
Member

Green now except for the removed build (==1.16.4) which can be ignored.

@martindurant

Copy link
Copy Markdown
Member

Clarification: if we open an array or group, and pass a dict-like as before, it gets wrapped to become a Store, right?

@joshmoorejoshmoore 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.

As mentioned on call, this is looking good. Thanks, @grlee77. Probably the most important remaining step is to get the release blurb so that we can all agree on the degree of breakage and have a comprehensive list of what (if anything) will no longer take dicts. Additionally some documentation may be necessary around the "pass by reference" semantics.

Propose then to target this for a 2.11

@joshmoore

Copy link
Copy Markdown
Member

Solved the (minor) merge conflict, @grlee77. From my side, I'd say let's try to get this into a RC as early as tomorrow. (Or someone else can do it this evening. I'm going to 🛏️ ) Up to you if you think we should also try to get metadata handling in.

(Release blurb would still be appreciated.)

@grlee77

Copy link
Copy Markdown
ContributorAuthor

Solved the (minor) merge conflict, @grlee77. From my side, I'd say let's try to get this into a RC as early as tomorrow. (Or someone else can do it this evening. I'm going to bed ) Up to you if you think we should also try to get metadata handling in.

I think we may as well also merge the metadata handling for the RC. Let's discuss in the community call.

One remaining doubt about the approach here is the presence of listdir and rmdir methods in this class which seems specific to our current v2 store implementations. They are not among the abstract store methods listed in the v3 spec (there is a list_dir, not listdir but behavior is not exactly the same. erase_prefix in the spec is like rmdir). I am wondering if we should instead hava a BaseStore that does not have these methods and then use a StoreV2 subclass that would add these?

A future StoreV3 class could then inherit from BaseStore instead of StoreV2, so that it would not have to inherit additional methods that are not part of the spec. That said, at the moment many high-level functions use listdir and rmdir, so we may want to keep them around, at least temporarily.

BaseStore does not have the listdir or rmdir methods
cleaned up some type declerations, making sure mypy passes
Otherwise the save_array doc example fails to write to a ZipStore
Comment threadzarr/storage.py
`Store` interface."""
path = normalize_storage_path(path)
if hasattr(store, "rmdir"):
if hasattr(store, "rmdir") and store.is_erasable(): # type: ignore

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.

Not a blocker for getting this into a 2.11 alpha build but is the hasattr not now redundant?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Not quite yet. There are calls to rmdir from _init_array_metadata (via init_array which still allows a MutableMapping for the store). This is why I put store as StoreLike in the type annotation, but then I had to add "# type: ignore" on this line or mypy complained that MutableMappings do not have an is_erasable attribute.

@joshmoore

Copy link
Copy Markdown
Member

As discussed during the community call yesterday evening (my time), merging this into a 2.11 alpha release with the (now passing) proposed changes.

Thanks to both @grlee77 and @Carreau for all their labors! 👏🏽

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.

6 participants

@grlee77@pep8speaks@joshmoore@jakirkham@martindurant@Carreau
, '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

Create a Base store class for Zarr Store (update) - #789

Merged
joshmoore merged 39 commits into
zarr-developers:masterfrom
grlee77:base-store-v2
Oct 21, 2021
Merged

Create a Base store class for Zarr Store (update)#789
joshmoore merged 39 commits into
zarr-developers:masterfrom
grlee77:base-store-v2

Conversation

@grlee77

Copy link
Copy Markdown
Contributor

Use a base Store class instead of just MutableMapping

I am resuming the work @Carreau started in #612 here. This is mostly just a rebase of that PR with a small new commit in 8136713. Matthias and I met earlier today and we decided that starting with this PR should make it easier to add zarr-v3 support without trying to implement an entirely independent set of classes. The goal is to reduce code duplication between v2 and v3 where possible (None of the changes in this PR are specific to v3 yet)

Note that I updated the version string text to 2.9.0 in a couple of places, but that may need to be updated again depending on when this is merged.

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
  • GitHub Actions have all passed
  • Test coverage is 100% (Codecov passes)

@pep8speaks

pep8speaks commented Jun 23, 2021

Copy link
Copy Markdown

Hello @grlee77! Thanks for updating this PR. We checked the lines you've touched for PEP 8 issues, and found:

There are currently no PEP 8 issues detected in this Pull Request. Cheers! 🍻

Comment last updated at 2021-10-21 04:50:40 UTC

@joshmoore

Copy link
Copy Markdown
Member

The Fatal Python error: Segmentation fault was also seen in #788 (comment)

@grlee77

grlee77 commented Jun 24, 2021

Copy link
Copy Markdown
ContributorAuthor

Yes, I just started looking into it. I can reproduce it locally after upgrading to NumPy 1.21. It does not occur for NumPy 1.20.3

@grlee77

Copy link
Copy Markdown
ContributorAuthor

I opened numpy/numpy#19325 regarding this segfault

@codecov

codecovBot commented Jun 24, 2021

Copy link
Copy Markdown

Codecov Report

Merging #789 (06086dc) into master (d8ac8a7) will increase coverage by 0.00%.
The diff coverage is 100.00%.

@@ Coverage Diff @@## master #789 +/- ##
=======================================
Coverage 99.94% 99.94% =======================================
Files 31 32 +1 Lines 11133 11175 +42 =======================================
+ Hits 11127 11169 +42 
Misses 6 6 
Impacted FilesCoverage Δ
zarr/_storage/absstore.py100.00% <100.00%> (ø)
zarr/_storage/store.py100.00% <100.00%> (ø)
zarr/attrs.py100.00% <100.00%> (ø)
zarr/convenience.py100.00% <100.00%> (ø)
zarr/core.py100.00% <100.00%> (ø)
zarr/creation.py100.00% <100.00%> (ø)
zarr/hierarchy.py100.00% <100.00%> (ø)
zarr/storage.py100.00% <100.00%> (ø)
zarr/tests/test_attrs.py100.00% <100.00%> (ø)
zarr/tests/test_convenience.py100.00% <100.00%> (ø)
... and 7 more

@grlee77grlee77 mentioned this pull request Jun 24, 2021
6 tasks
@jakirkham

Copy link
Copy Markdown
Member

cc @martindurant@rabernat@jhamman@shoyer@shikharsg (in case any of you have thoughts here 🙂 this will affect how other store implementations work 😉)

@jakirkham

Copy link
Copy Markdown
Member

Also cc @TomAugspurger 🙂

@grlee77

Copy link
Copy Markdown
ContributorAuthor

Looking ahead to adding v3 spec support:

In terms of class members for a Store interface, the v3 spec indicates the following should be present:

  • readable stores must have: get
  • writeable stores must have : set, erase, erase_prefix
  • listable stores should have one or more of: list, list_dir, list_prefix:

The Store class here matches the existing store implementations in zarr-python in that it has a listdir method, but this differs from the list_dir spelling in the v3 spec which is unfortunate. erase seems equivalent to __delitem__ while erase_prefix seems equivalent to rmdir

@joshmoore

Copy link
Copy Markdown
Member

Green now except for the removed build (==1.16.4) which can be ignored.

@martindurant

Copy link
Copy Markdown
Member

Clarification: if we open an array or group, and pass a dict-like as before, it gets wrapped to become a Store, right?

@joshmoorejoshmoore 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.

As mentioned on call, this is looking good. Thanks, @grlee77. Probably the most important remaining step is to get the release blurb so that we can all agree on the degree of breakage and have a comprehensive list of what (if anything) will no longer take dicts. Additionally some documentation may be necessary around the "pass by reference" semantics.

Propose then to target this for a 2.11

@joshmoore

Copy link
Copy Markdown
Member

Solved the (minor) merge conflict, @grlee77. From my side, I'd say let's try to get this into a RC as early as tomorrow. (Or someone else can do it this evening. I'm going to 🛏️ ) Up to you if you think we should also try to get metadata handling in.

(Release blurb would still be appreciated.)

@grlee77

Copy link
Copy Markdown
ContributorAuthor

Solved the (minor) merge conflict, @grlee77. From my side, I'd say let's try to get this into a RC as early as tomorrow. (Or someone else can do it this evening. I'm going to bed ) Up to you if you think we should also try to get metadata handling in.

I think we may as well also merge the metadata handling for the RC. Let's discuss in the community call.

One remaining doubt about the approach here is the presence of listdir and rmdir methods in this class which seems specific to our current v2 store implementations. They are not among the abstract store methods listed in the v3 spec (there is a list_dir, not listdir but behavior is not exactly the same. erase_prefix in the spec is like rmdir). I am wondering if we should instead hava a BaseStore that does not have these methods and then use a StoreV2 subclass that would add these?

A future StoreV3 class could then inherit from BaseStore instead of StoreV2, so that it would not have to inherit additional methods that are not part of the spec. That said, at the moment many high-level functions use listdir and rmdir, so we may want to keep them around, at least temporarily.

BaseStore does not have the listdir or rmdir methods
cleaned up some type declerations, making sure mypy passes
Otherwise the save_array doc example fails to write to a ZipStore
Comment threadzarr/storage.py
`Store` interface."""
path = normalize_storage_path(path)
if hasattr(store, "rmdir"):
if hasattr(store, "rmdir") and store.is_erasable(): # type: ignore

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.

Not a blocker for getting this into a 2.11 alpha build but is the hasattr not now redundant?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Not quite yet. There are calls to rmdir from _init_array_metadata (via init_array which still allows a MutableMapping for the store). This is why I put store as StoreLike in the type annotation, but then I had to add "# type: ignore" on this line or mypy complained that MutableMappings do not have an is_erasable attribute.

@joshmoore

Copy link
Copy Markdown
Member

As discussed during the community call yesterday evening (my time), merging this into a 2.11 alpha release with the (now passing) proposed changes.

Thanks to both @grlee77 and @Carreau for all their labors! 👏🏽

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.

6 participants

@grlee77@pep8speaks@joshmoore@jakirkham@martindurant@Carreau
, '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

Create a Base store class for Zarr Store (update) - #789

Merged
joshmoore merged 39 commits into
zarr-developers:masterfrom
grlee77:base-store-v2
Oct 21, 2021
Merged

Create a Base store class for Zarr Store (update)#789
joshmoore merged 39 commits into
zarr-developers:masterfrom
grlee77:base-store-v2

Conversation

@grlee77

Copy link
Copy Markdown
Contributor

Use a base Store class instead of just MutableMapping

I am resuming the work @Carreau started in #612 here. This is mostly just a rebase of that PR with a small new commit in 8136713. Matthias and I met earlier today and we decided that starting with this PR should make it easier to add zarr-v3 support without trying to implement an entirely independent set of classes. The goal is to reduce code duplication between v2 and v3 where possible (None of the changes in this PR are specific to v3 yet)

Note that I updated the version string text to 2.9.0 in a couple of places, but that may need to be updated again depending on when this is merged.

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
  • GitHub Actions have all passed
  • Test coverage is 100% (Codecov passes)

@pep8speaks

pep8speaks commented Jun 23, 2021

Copy link
Copy Markdown

Hello @grlee77! Thanks for updating this PR. We checked the lines you've touched for PEP 8 issues, and found:

There are currently no PEP 8 issues detected in this Pull Request. Cheers! 🍻

Comment last updated at 2021-10-21 04:50:40 UTC

@joshmoore

Copy link
Copy Markdown
Member

The Fatal Python error: Segmentation fault was also seen in #788 (comment)

@grlee77

grlee77 commented Jun 24, 2021

Copy link
Copy Markdown
ContributorAuthor

Yes, I just started looking into it. I can reproduce it locally after upgrading to NumPy 1.21. It does not occur for NumPy 1.20.3

@grlee77

Copy link
Copy Markdown
ContributorAuthor

I opened numpy/numpy#19325 regarding this segfault

@codecov

codecovBot commented Jun 24, 2021

Copy link
Copy Markdown

Codecov Report

Merging #789 (06086dc) into master (d8ac8a7) will increase coverage by 0.00%.
The diff coverage is 100.00%.

@@ Coverage Diff @@## master #789 +/- ##
=======================================
Coverage 99.94% 99.94% =======================================
Files 31 32 +1 Lines 11133 11175 +42 =======================================
+ Hits 11127 11169 +42 
Misses 6 6 
Impacted FilesCoverage Δ
zarr/_storage/absstore.py100.00% <100.00%> (ø)
zarr/_storage/store.py100.00% <100.00%> (ø)
zarr/attrs.py100.00% <100.00%> (ø)
zarr/convenience.py100.00% <100.00%> (ø)
zarr/core.py100.00% <100.00%> (ø)
zarr/creation.py100.00% <100.00%> (ø)
zarr/hierarchy.py100.00% <100.00%> (ø)
zarr/storage.py100.00% <100.00%> (ø)
zarr/tests/test_attrs.py100.00% <100.00%> (ø)
zarr/tests/test_convenience.py100.00% <100.00%> (ø)
... and 7 more

@grlee77grlee77 mentioned this pull request Jun 24, 2021
6 tasks
@jakirkham

Copy link
Copy Markdown
Member

cc @martindurant@rabernat@jhamman@shoyer@shikharsg (in case any of you have thoughts here 🙂 this will affect how other store implementations work 😉)

@jakirkham

Copy link
Copy Markdown
Member

Also cc @TomAugspurger 🙂

@grlee77

Copy link
Copy Markdown
ContributorAuthor

Looking ahead to adding v3 spec support:

In terms of class members for a Store interface, the v3 spec indicates the following should be present:

  • readable stores must have: get
  • writeable stores must have : set, erase, erase_prefix
  • listable stores should have one or more of: list, list_dir, list_prefix:

The Store class here matches the existing store implementations in zarr-python in that it has a listdir method, but this differs from the list_dir spelling in the v3 spec which is unfortunate. erase seems equivalent to __delitem__ while erase_prefix seems equivalent to rmdir

@joshmoore

Copy link
Copy Markdown
Member

Green now except for the removed build (==1.16.4) which can be ignored.

@martindurant

Copy link
Copy Markdown
Member

Clarification: if we open an array or group, and pass a dict-like as before, it gets wrapped to become a Store, right?

@joshmoorejoshmoore 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.

As mentioned on call, this is looking good. Thanks, @grlee77. Probably the most important remaining step is to get the release blurb so that we can all agree on the degree of breakage and have a comprehensive list of what (if anything) will no longer take dicts. Additionally some documentation may be necessary around the "pass by reference" semantics.

Propose then to target this for a 2.11

@joshmoore

Copy link
Copy Markdown
Member

Solved the (minor) merge conflict, @grlee77. From my side, I'd say let's try to get this into a RC as early as tomorrow. (Or someone else can do it this evening. I'm going to 🛏️ ) Up to you if you think we should also try to get metadata handling in.

(Release blurb would still be appreciated.)

@grlee77

Copy link
Copy Markdown
ContributorAuthor

Solved the (minor) merge conflict, @grlee77. From my side, I'd say let's try to get this into a RC as early as tomorrow. (Or someone else can do it this evening. I'm going to bed ) Up to you if you think we should also try to get metadata handling in.

I think we may as well also merge the metadata handling for the RC. Let's discuss in the community call.

One remaining doubt about the approach here is the presence of listdir and rmdir methods in this class which seems specific to our current v2 store implementations. They are not among the abstract store methods listed in the v3 spec (there is a list_dir, not listdir but behavior is not exactly the same. erase_prefix in the spec is like rmdir). I am wondering if we should instead hava a BaseStore that does not have these methods and then use a StoreV2 subclass that would add these?

A future StoreV3 class could then inherit from BaseStore instead of StoreV2, so that it would not have to inherit additional methods that are not part of the spec. That said, at the moment many high-level functions use listdir and rmdir, so we may want to keep them around, at least temporarily.

BaseStore does not have the listdir or rmdir methods
cleaned up some type declerations, making sure mypy passes
Otherwise the save_array doc example fails to write to a ZipStore
Comment threadzarr/storage.py
`Store` interface."""
path = normalize_storage_path(path)
if hasattr(store, "rmdir"):
if hasattr(store, "rmdir") and store.is_erasable(): # type: ignore

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.

Not a blocker for getting this into a 2.11 alpha build but is the hasattr not now redundant?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Not quite yet. There are calls to rmdir from _init_array_metadata (via init_array which still allows a MutableMapping for the store). This is why I put store as StoreLike in the type annotation, but then I had to add "# type: ignore" on this line or mypy complained that MutableMappings do not have an is_erasable attribute.

@joshmoore

Copy link
Copy Markdown
Member

As discussed during the community call yesterday evening (my time), merging this into a 2.11 alpha release with the (now passing) proposed changes.

Thanks to both @grlee77 and @Carreau for all their labors! 👏🏽

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.

6 participants

@grlee77@pep8speaks@joshmoore@jakirkham@martindurant@Carreau
, '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

Create a Base store class for Zarr Store (update) - #789

Merged
joshmoore merged 39 commits into
zarr-developers:masterfrom
grlee77:base-store-v2
Oct 21, 2021
Merged

Create a Base store class for Zarr Store (update)#789
joshmoore merged 39 commits into
zarr-developers:masterfrom
grlee77:base-store-v2

Conversation

@grlee77

Copy link
Copy Markdown
Contributor

Use a base Store class instead of just MutableMapping

I am resuming the work @Carreau started in #612 here. This is mostly just a rebase of that PR with a small new commit in 8136713. Matthias and I met earlier today and we decided that starting with this PR should make it easier to add zarr-v3 support without trying to implement an entirely independent set of classes. The goal is to reduce code duplication between v2 and v3 where possible (None of the changes in this PR are specific to v3 yet)

Note that I updated the version string text to 2.9.0 in a couple of places, but that may need to be updated again depending on when this is merged.

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
  • GitHub Actions have all passed
  • Test coverage is 100% (Codecov passes)

@pep8speaks

pep8speaks commented Jun 23, 2021

Copy link
Copy Markdown

Hello @grlee77! Thanks for updating this PR. We checked the lines you've touched for PEP 8 issues, and found:

There are currently no PEP 8 issues detected in this Pull Request. Cheers! 🍻

Comment last updated at 2021-10-21 04:50:40 UTC

@joshmoore

Copy link
Copy Markdown
Member

The Fatal Python error: Segmentation fault was also seen in #788 (comment)

@grlee77

grlee77 commented Jun 24, 2021

Copy link
Copy Markdown
ContributorAuthor

Yes, I just started looking into it. I can reproduce it locally after upgrading to NumPy 1.21. It does not occur for NumPy 1.20.3

@grlee77

Copy link
Copy Markdown
ContributorAuthor

I opened numpy/numpy#19325 regarding this segfault

@codecov

codecovBot commented Jun 24, 2021

Copy link
Copy Markdown

Codecov Report

Merging #789 (06086dc) into master (d8ac8a7) will increase coverage by 0.00%.
The diff coverage is 100.00%.

@@ Coverage Diff @@## master #789 +/- ##
=======================================
Coverage 99.94% 99.94% =======================================
Files 31 32 +1 Lines 11133 11175 +42 =======================================
+ Hits 11127 11169 +42 
Misses 6 6 
Impacted FilesCoverage Δ
zarr/_storage/absstore.py100.00% <100.00%> (ø)
zarr/_storage/store.py100.00% <100.00%> (ø)
zarr/attrs.py100.00% <100.00%> (ø)
zarr/convenience.py100.00% <100.00%> (ø)
zarr/core.py100.00% <100.00%> (ø)
zarr/creation.py100.00% <100.00%> (ø)
zarr/hierarchy.py100.00% <100.00%> (ø)
zarr/storage.py100.00% <100.00%> (ø)
zarr/tests/test_attrs.py100.00% <100.00%> (ø)
zarr/tests/test_convenience.py100.00% <100.00%> (ø)
... and 7 more

@grlee77grlee77 mentioned this pull request Jun 24, 2021
6 tasks
@jakirkham

Copy link
Copy Markdown
Member

cc @martindurant@rabernat@jhamman@shoyer@shikharsg (in case any of you have thoughts here 🙂 this will affect how other store implementations work 😉)

@jakirkham

Copy link
Copy Markdown
Member

Also cc @TomAugspurger 🙂

@grlee77

Copy link
Copy Markdown
ContributorAuthor

Looking ahead to adding v3 spec support:

In terms of class members for a Store interface, the v3 spec indicates the following should be present:

  • readable stores must have: get
  • writeable stores must have : set, erase, erase_prefix
  • listable stores should have one or more of: list, list_dir, list_prefix:

The Store class here matches the existing store implementations in zarr-python in that it has a listdir method, but this differs from the list_dir spelling in the v3 spec which is unfortunate. erase seems equivalent to __delitem__ while erase_prefix seems equivalent to rmdir

@joshmoore

Copy link
Copy Markdown
Member

Green now except for the removed build (==1.16.4) which can be ignored.

@martindurant

Copy link
Copy Markdown
Member

Clarification: if we open an array or group, and pass a dict-like as before, it gets wrapped to become a Store, right?

@joshmoorejoshmoore 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.

As mentioned on call, this is looking good. Thanks, @grlee77. Probably the most important remaining step is to get the release blurb so that we can all agree on the degree of breakage and have a comprehensive list of what (if anything) will no longer take dicts. Additionally some documentation may be necessary around the "pass by reference" semantics.

Propose then to target this for a 2.11

@joshmoore

Copy link
Copy Markdown
Member

Solved the (minor) merge conflict, @grlee77. From my side, I'd say let's try to get this into a RC as early as tomorrow. (Or someone else can do it this evening. I'm going to 🛏️ ) Up to you if you think we should also try to get metadata handling in.

(Release blurb would still be appreciated.)

@grlee77

Copy link
Copy Markdown
ContributorAuthor

Solved the (minor) merge conflict, @grlee77. From my side, I'd say let's try to get this into a RC as early as tomorrow. (Or someone else can do it this evening. I'm going to bed ) Up to you if you think we should also try to get metadata handling in.

I think we may as well also merge the metadata handling for the RC. Let's discuss in the community call.

One remaining doubt about the approach here is the presence of listdir and rmdir methods in this class which seems specific to our current v2 store implementations. They are not among the abstract store methods listed in the v3 spec (there is a list_dir, not listdir but behavior is not exactly the same. erase_prefix in the spec is like rmdir). I am wondering if we should instead hava a BaseStore that does not have these methods and then use a StoreV2 subclass that would add these?

A future StoreV3 class could then inherit from BaseStore instead of StoreV2, so that it would not have to inherit additional methods that are not part of the spec. That said, at the moment many high-level functions use listdir and rmdir, so we may want to keep them around, at least temporarily.

BaseStore does not have the listdir or rmdir methods
cleaned up some type declerations, making sure mypy passes
Otherwise the save_array doc example fails to write to a ZipStore
Comment threadzarr/storage.py
`Store` interface."""
path = normalize_storage_path(path)
if hasattr(store, "rmdir"):
if hasattr(store, "rmdir") and store.is_erasable(): # type: ignore

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.

Not a blocker for getting this into a 2.11 alpha build but is the hasattr not now redundant?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Not quite yet. There are calls to rmdir from _init_array_metadata (via init_array which still allows a MutableMapping for the store). This is why I put store as StoreLike in the type annotation, but then I had to add "# type: ignore" on this line or mypy complained that MutableMappings do not have an is_erasable attribute.

@joshmoore

Copy link
Copy Markdown
Member

As discussed during the community call yesterday evening (my time), merging this into a 2.11 alpha release with the (now passing) proposed changes.

Thanks to both @grlee77 and @Carreau for all their labors! 👏🏽

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.

6 participants

@grlee77@pep8speaks@joshmoore@jakirkham@martindurant@Carreau
, '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

Create a Base store class for Zarr Store (update) - #789

Merged
joshmoore merged 39 commits into
zarr-developers:masterfrom
grlee77:base-store-v2
Oct 21, 2021
Merged

Create a Base store class for Zarr Store (update)#789
joshmoore merged 39 commits into
zarr-developers:masterfrom
grlee77:base-store-v2

Conversation

@grlee77

Copy link
Copy Markdown
Contributor

Use a base Store class instead of just MutableMapping

I am resuming the work @Carreau started in #612 here. This is mostly just a rebase of that PR with a small new commit in 8136713. Matthias and I met earlier today and we decided that starting with this PR should make it easier to add zarr-v3 support without trying to implement an entirely independent set of classes. The goal is to reduce code duplication between v2 and v3 where possible (None of the changes in this PR are specific to v3 yet)

Note that I updated the version string text to 2.9.0 in a couple of places, but that may need to be updated again depending on when this is merged.

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
  • GitHub Actions have all passed
  • Test coverage is 100% (Codecov passes)

@pep8speaks

pep8speaks commented Jun 23, 2021

Copy link
Copy Markdown

Hello @grlee77! Thanks for updating this PR. We checked the lines you've touched for PEP 8 issues, and found:

There are currently no PEP 8 issues detected in this Pull Request. Cheers! 🍻

Comment last updated at 2021-10-21 04:50:40 UTC

@joshmoore

Copy link
Copy Markdown
Member

The Fatal Python error: Segmentation fault was also seen in #788 (comment)

@grlee77

grlee77 commented Jun 24, 2021

Copy link
Copy Markdown
ContributorAuthor

Yes, I just started looking into it. I can reproduce it locally after upgrading to NumPy 1.21. It does not occur for NumPy 1.20.3

@grlee77

Copy link
Copy Markdown
ContributorAuthor

I opened numpy/numpy#19325 regarding this segfault

@codecov

codecovBot commented Jun 24, 2021

Copy link
Copy Markdown

Codecov Report

Merging #789 (06086dc) into master (d8ac8a7) will increase coverage by 0.00%.
The diff coverage is 100.00%.

@@ Coverage Diff @@## master #789 +/- ##
=======================================
Coverage 99.94% 99.94% =======================================
Files 31 32 +1 Lines 11133 11175 +42 =======================================
+ Hits 11127 11169 +42 
Misses 6 6 
Impacted FilesCoverage Δ
zarr/_storage/absstore.py100.00% <100.00%> (ø)
zarr/_storage/store.py100.00% <100.00%> (ø)
zarr/attrs.py100.00% <100.00%> (ø)
zarr/convenience.py100.00% <100.00%> (ø)
zarr/core.py100.00% <100.00%> (ø)
zarr/creation.py100.00% <100.00%> (ø)
zarr/hierarchy.py100.00% <100.00%> (ø)
zarr/storage.py100.00% <100.00%> (ø)
zarr/tests/test_attrs.py100.00% <100.00%> (ø)
zarr/tests/test_convenience.py100.00% <100.00%> (ø)
... and 7 more

@grlee77grlee77 mentioned this pull request Jun 24, 2021
6 tasks
@jakirkham

Copy link
Copy Markdown
Member

cc @martindurant@rabernat@jhamman@shoyer@shikharsg (in case any of you have thoughts here 🙂 this will affect how other store implementations work 😉)

@jakirkham

Copy link
Copy Markdown
Member

Also cc @TomAugspurger 🙂

@grlee77

Copy link
Copy Markdown
ContributorAuthor

Looking ahead to adding v3 spec support:

In terms of class members for a Store interface, the v3 spec indicates the following should be present:

  • readable stores must have: get
  • writeable stores must have : set, erase, erase_prefix
  • listable stores should have one or more of: list, list_dir, list_prefix:

The Store class here matches the existing store implementations in zarr-python in that it has a listdir method, but this differs from the list_dir spelling in the v3 spec which is unfortunate. erase seems equivalent to __delitem__ while erase_prefix seems equivalent to rmdir

@joshmoore

Copy link
Copy Markdown
Member

Green now except for the removed build (==1.16.4) which can be ignored.

@martindurant

Copy link
Copy Markdown
Member

Clarification: if we open an array or group, and pass a dict-like as before, it gets wrapped to become a Store, right?

@joshmoorejoshmoore 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.

As mentioned on call, this is looking good. Thanks, @grlee77. Probably the most important remaining step is to get the release blurb so that we can all agree on the degree of breakage and have a comprehensive list of what (if anything) will no longer take dicts. Additionally some documentation may be necessary around the "pass by reference" semantics.

Propose then to target this for a 2.11

@joshmoore

Copy link
Copy Markdown
Member

Solved the (minor) merge conflict, @grlee77. From my side, I'd say let's try to get this into a RC as early as tomorrow. (Or someone else can do it this evening. I'm going to 🛏️ ) Up to you if you think we should also try to get metadata handling in.

(Release blurb would still be appreciated.)

@grlee77

Copy link
Copy Markdown
ContributorAuthor

Solved the (minor) merge conflict, @grlee77. From my side, I'd say let's try to get this into a RC as early as tomorrow. (Or someone else can do it this evening. I'm going to bed ) Up to you if you think we should also try to get metadata handling in.

I think we may as well also merge the metadata handling for the RC. Let's discuss in the community call.

One remaining doubt about the approach here is the presence of listdir and rmdir methods in this class which seems specific to our current v2 store implementations. They are not among the abstract store methods listed in the v3 spec (there is a list_dir, not listdir but behavior is not exactly the same. erase_prefix in the spec is like rmdir). I am wondering if we should instead hava a BaseStore that does not have these methods and then use a StoreV2 subclass that would add these?

A future StoreV3 class could then inherit from BaseStore instead of StoreV2, so that it would not have to inherit additional methods that are not part of the spec. That said, at the moment many high-level functions use listdir and rmdir, so we may want to keep them around, at least temporarily.

BaseStore does not have the listdir or rmdir methods
cleaned up some type declerations, making sure mypy passes
Otherwise the save_array doc example fails to write to a ZipStore
Comment threadzarr/storage.py
`Store` interface."""
path = normalize_storage_path(path)
if hasattr(store, "rmdir"):
if hasattr(store, "rmdir") and store.is_erasable(): # type: ignore

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.

Not a blocker for getting this into a 2.11 alpha build but is the hasattr not now redundant?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Not quite yet. There are calls to rmdir from _init_array_metadata (via init_array which still allows a MutableMapping for the store). This is why I put store as StoreLike in the type annotation, but then I had to add "# type: ignore" on this line or mypy complained that MutableMappings do not have an is_erasable attribute.

@joshmoore

Copy link
Copy Markdown
Member

As discussed during the community call yesterday evening (my time), merging this into a 2.11 alpha release with the (now passing) proposed changes.

Thanks to both @grlee77 and @Carreau for all their labors! 👏🏽

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.

6 participants

@grlee77@pep8speaks@joshmoore@jakirkham@martindurant@Carreau