napari-plugin-manager 0.1.6__py3-none-any.whl → 0.1.7__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -104,7 +104,7 @@ def iter_napari_plugin_info() -> Iterator[tuple[PackageMetadata, bool, dict]]:
104
104
  info_copy.pop('display_name', None)
105
105
  pypi_versions = info_copy.pop('pypi_versions')
106
106
  conda_versions = info_copy.pop('conda_versions')
107
- info_ = cast(_ShortSummaryDict, info_copy)
107
+ info_ = cast('_ShortSummaryDict', info_copy)
108
108
  home_page = get_homepage_url(info_copy)
109
109
  # this URL is used for the widget, so we have to replace the home_page
110
110
  # link here as well as returning it in extra_info
@@ -122,12 +122,12 @@ def iter_napari_plugin_info() -> Iterator[tuple[PackageMetadata, bool, dict]]:
122
122
  'conda_versions': conda_versions,
123
123
  }
124
124
  info_['name'] = normalized_name(info_['name'])
125
- meta = PackageMetadata(**info_) # type:ignore[call-arg]
125
+ meta = PackageMetadata(**info_)
126
126
 
127
127
  yield meta, (info_['name'] in conda_set), extra_info
128
128
 
129
129
 
130
- def cache_clear():
130
+ def cache_clear() -> None:
131
131
  """Clear the cache for all cached functions in this module."""
132
132
  plugin_summaries.cache_clear()
133
133
  conda_map.cache_clear()
@@ -10,28 +10,30 @@ by a `deque` of `*InstallerTool` dataclasses (`NapariPipInstallerTool` and
10
10
  import atexit
11
11
  import os
12
12
  import sys
13
- from collections.abc import Sequence
14
13
  from functools import lru_cache
15
14
  from pathlib import Path
16
15
  from tempfile import NamedTemporaryFile
17
16
 
18
- from napari._version import version as _napari_version
19
- from napari._version import version_tuple as _napari_version_tuple
17
+ from napari._version import (
18
+ version as _napari_version,
19
+ version_tuple as _napari_version_tuple,
20
+ )
20
21
 
21
22
  from napari_plugin_manager.base_qt_package_installer import (
22
23
  CondaInstallerTool,
23
24
  InstallerQueue,
24
25
  PipInstallerTool,
26
+ UvInstallerTool,
25
27
  )
26
28
 
27
29
 
28
- def _get_python_exe():
30
+ def _get_python_exe() -> str:
29
31
  # Note: is_bundled_app() returns False even if using a Briefcase bundle...
30
32
  # Workaround: see if sys.executable is set to something something napari on Mac
31
33
  if (
32
- sys.executable.endswith("napari")
34
+ sys.executable.endswith('napari')
33
35
  and sys.platform == 'darwin'
34
- and (python := Path(sys.prefix) / "bin" / "python3").is_file()
36
+ and (python := Path(sys.prefix) / 'bin' / 'python3').is_file()
35
37
  ):
36
38
  # sys.prefix should be <napari.app>/Contents/Resources/Support/Python/Resources
37
39
  return str(python)
@@ -40,30 +42,52 @@ def _get_python_exe():
40
42
 
41
43
  class NapariPipInstallerTool(PipInstallerTool):
42
44
  @classmethod
43
- def executable(cls):
45
+ def executable(cls) -> str:
44
46
  return str(_get_python_exe())
45
47
 
46
48
  @staticmethod
47
- def constraints() -> Sequence[str]:
49
+ def constraints() -> list[str]:
48
50
  """
49
51
  Version constraints to limit unwanted changes in installation.
50
52
  """
51
- return [f"napari=={_napari_version}"]
53
+ return [f'napari=={_napari_version}']
52
54
 
53
55
  @classmethod
54
56
  @lru_cache(maxsize=0)
55
57
  def _constraints_file(cls) -> str:
56
58
  with NamedTemporaryFile(
57
- "w", suffix="-napari-constraints.txt", delete=False
59
+ 'w', suffix='-napari-constraints.txt', delete=False
58
60
  ) as f:
59
- f.write("\n".join(cls.constraints()))
61
+ f.write('\n'.join(cls.constraints()))
60
62
  atexit.register(os.unlink, f.name)
61
63
  return f.name
62
64
 
63
65
 
66
+ class NapariUvInstallerTool(UvInstallerTool):
67
+ @staticmethod
68
+ def constraints() -> list[str]:
69
+ """
70
+ Version constraints to limit unwanted changes in installation.
71
+ """
72
+ return [f'napari=={_napari_version}']
73
+
74
+ @classmethod
75
+ @lru_cache(maxsize=0)
76
+ def _constraints_file(cls) -> str:
77
+ with NamedTemporaryFile(
78
+ 'w', suffix='-napari-constraints.txt', delete=False
79
+ ) as f:
80
+ f.write('\n'.join(cls.constraints()))
81
+ atexit.register(os.unlink, f.name)
82
+ return f.name
83
+
84
+ def _python_executable(self) -> str:
85
+ return str(_get_python_exe())
86
+
87
+
64
88
  class NapariCondaInstallerTool(CondaInstallerTool):
65
89
  @staticmethod
66
- def constraints() -> Sequence[str]:
90
+ def constraints() -> list[str]:
67
91
  # FIXME
68
92
  # dev or rc versions might not be available in public channels
69
93
  # but only installed locally - if we try to pin those, mamba
@@ -71,14 +95,18 @@ class NapariCondaInstallerTool(CondaInstallerTool):
71
95
  # in the remote index, only locally; to work around this bug
72
96
  # we will have to pin to e.g. 0.4.* instead of 0.4.17.* for now
73
97
  version_lower = _napari_version.lower()
74
- is_dev = "rc" in version_lower or "dev" in version_lower
98
+ is_dev = 'rc' in version_lower or 'dev' in version_lower
75
99
  pin_level = 2 if is_dev else 3
76
- version = ".".join([str(x) for x in _napari_version_tuple[:pin_level]])
100
+ version = '.'.join([str(x) for x in _napari_version_tuple[:pin_level]])
77
101
 
78
- return [f"napari={version}"]
102
+ return [f'napari={version}']
79
103
 
80
104
 
81
105
  class NapariInstallerQueue(InstallerQueue):
82
- PIP_INSTALLER_TOOL_CLASS = NapariPipInstallerTool
106
+ PYPI_INSTALLER_TOOL_CLASS = (
107
+ NapariUvInstallerTool
108
+ if NapariUvInstallerTool.available()
109
+ else NapariPipInstallerTool
110
+ )
83
111
  CONDA_INSTALLER_TOOL_CLASS = NapariCondaInstallerTool
84
112
  BASE_PACKAGE_NAME = 'napari'
@@ -4,7 +4,10 @@ from pathlib import Path
4
4
  import napari.plugins
5
5
  import napari.resources
6
6
  import npe2
7
- from napari._qt.qt_resources import QColoredSVGIcon, get_current_stylesheet
7
+ from napari._qt.qt_resources import (
8
+ QColoredSVGIcon,
9
+ get_stylesheet,
10
+ )
8
11
  from napari._qt.qthreading import create_worker
9
12
  from napari._qt.widgets.qt_tooltip import QtToolTipLabel
10
13
  from napari.plugins.utils import normalized_name
@@ -50,35 +53,35 @@ class PluginListItem(BasePluginListItem):
50
53
  """An entry in the plugin dialog. This will include the package name, summary,
51
54
  author, source, version, and buttons to update, install/uninstall, etc."""
52
55
 
53
- BASE_PACKAGE_NAME = 'napari'
56
+ BASE_PACKAGE_NAME: str = 'napari'
54
57
 
55
- def _warning_icon(self):
58
+ def _warning_icon(self) -> QColoredSVGIcon:
56
59
  # TODO: This color should come from the theme but the theme needs
57
60
  # to provide the right color. Default warning should be orange, not
58
61
  # red. Code example:
59
62
  # theme_name = get_settings().appearance.theme
60
63
  # napari.utils.theme.get_theme(theme_name, as_dict=False).warning.as_hex()
61
- return QColoredSVGIcon.from_resources("warning").colored(
62
- color="#E3B617"
64
+ return QColoredSVGIcon.from_resources('warning').colored(
65
+ color='#E3B617'
63
66
  )
64
67
 
65
- def _collapsed_icon(self):
68
+ def _collapsed_icon(self) -> QColoredSVGIcon:
66
69
  return QColoredSVGIcon.from_resources('right_arrow').colored(
67
70
  color='white'
68
71
  )
69
72
 
70
- def _expanded_icon(self):
73
+ def _expanded_icon(self) -> QColoredSVGIcon:
71
74
  return QColoredSVGIcon.from_resources('down_arrow').colored(
72
75
  color='white'
73
76
  )
74
77
 
75
- def _warning_tooltip(self):
78
+ def _warning_tooltip(self) -> QtToolTipLabel:
76
79
  return QtToolTipLabel(self)
77
80
 
78
- def _trans(self, text, **kwargs):
81
+ def _trans(self, text, **kwargs) -> str:
79
82
  return trans._(text, **kwargs)
80
83
 
81
- def _handle_plugin_api_version(self, plugin_api_version):
84
+ def _handle_plugin_api_version(self, plugin_api_version: str) -> None:
82
85
  if plugin_api_version in (None, 1):
83
86
  return
84
87
 
@@ -93,7 +96,7 @@ class PluginListItem(BasePluginListItem):
93
96
  )
94
97
  self.set_status(icon.pixmap(20, 20), text)
95
98
 
96
- def _on_enabled_checkbox(self, state: int):
99
+ def _on_enabled_checkbox(self, state: int) -> None:
97
100
  """Called with `state` when checkbox is clicked."""
98
101
  enabled = bool(state)
99
102
  plugin_name = self.plugin_name.text()
@@ -113,15 +116,17 @@ class PluginListItem(BasePluginListItem):
113
116
  )
114
117
  return
115
118
 
116
- def _warn_pypi_install(self):
119
+ def _warn_pypi_install(self) -> bool:
117
120
  return running_as_constructor_app() or is_conda_package(
118
121
  'napari'
119
122
  ) # or True
120
123
 
121
- def _action_validation(self, tool, action):
124
+ def _action_validation(
125
+ self, tool: InstallerTools, action: InstallerActions
126
+ ) -> bool:
122
127
  global DISMISS_WARN_PYPI_INSTALL_DLG
123
128
  if (
124
- tool == InstallerTools.PIP
129
+ tool == InstallerTools.PYPI
125
130
  and action == InstallerActions.INSTALL
126
131
  and self._warn_pypi_install()
127
132
  and not DISMISS_WARN_PYPI_INSTALL_DLG
@@ -157,29 +162,34 @@ class PluginListItem(BasePluginListItem):
157
162
 
158
163
 
159
164
  class QPluginList(BaseQPluginList):
160
-
161
165
  PLUGIN_LIST_ITEM_CLASS = PluginListItem
162
166
 
163
- def _trans(self, text, **kwargs):
167
+ def _trans(self, text: str, **kwargs) -> str:
164
168
  return trans._(text, **kwargs)
165
169
 
166
170
 
167
171
  class QtPluginDialog(BaseQtPluginDialog):
168
-
169
172
  PACKAGE_METADATA_CLASS = npe2.PackageMetadata
170
173
  PROJECT_INFO_VERSION_CLASS = ProjectInfoVersions
171
174
  PLUGIN_LIST_CLASS = QPluginList
172
175
  INSTALLER_QUEUE_CLASS = NapariInstallerQueue
173
176
  BASE_PACKAGE_NAME = 'napari'
174
177
 
175
- def _setup_theme_update(self):
176
- get_settings().appearance.events.theme.connect(self._update_theme)
178
+ def _setup_theme_update(self) -> None:
179
+ settings = get_settings()
180
+ settings.appearance.events.theme.connect(self._update_theme)
181
+ settings.appearance.events.font_size.connect(self._update_theme)
177
182
 
178
- def _update_theme(self, event):
179
- stylesheet = get_current_stylesheet([STYLES_PATH])
183
+ def _update_theme(self, event) -> None:
184
+ settings = get_settings()
185
+ theme = settings.appearance.theme
186
+ font_variable = {'font_size': f'{settings.appearance.font_size}pt'}
187
+ stylesheet = get_stylesheet(
188
+ theme, extra=[STYLES_PATH], extra_variables=font_variable
189
+ )
180
190
  self.setStyleSheet(stylesheet)
181
191
 
182
- def _add_installed(self, pkg_name=None):
192
+ def _add_installed(self, pkg_name: str | None = None) -> None:
183
193
  use_npe2_adaptor = get_settings().plugins.use_npe2_adaptor
184
194
  pm2 = npe2.PluginManager.instance()
185
195
  pm2.discover(include_npe1=use_npe2_adaptor)
@@ -231,7 +241,7 @@ class QtPluginDialog(BaseQtPluginDialog):
231
241
  self.installed_list.setCurrentItem(item)
232
242
  break
233
243
 
234
- def _fetch_available_plugins(self, clear_cache: bool = False):
244
+ def _fetch_available_plugins(self, clear_cache: bool = False) -> None:
235
245
  settings = get_settings()
236
246
  use_npe2_adaptor = settings.plugins.use_npe2_adaptor
237
247
 
@@ -249,26 +259,26 @@ class QtPluginDialog(BaseQtPluginDialog):
249
259
  pm2 = npe2.PluginManager.instance()
250
260
  pm2.discover(include_npe1=use_npe2_adaptor)
251
261
 
252
- def _loading_gif(self):
253
- load_gif = str(Path(napari.resources.__file__).parent / "loading.gif")
262
+ def _loading_gif(self) -> QMovie:
263
+ load_gif = str(Path(napari.resources.__file__).parent / 'loading.gif')
254
264
  mov = QMovie(load_gif)
255
265
  mov.setScaledSize(QSize(18, 18))
256
266
  return mov
257
267
 
258
- def _on_bundle(self):
268
+ def _on_bundle(self) -> bool:
259
269
  return running_as_constructor_app()
260
270
 
261
- def _show_info(self, info):
271
+ def _show_info(self, info: str) -> None:
262
272
  show_info(info)
263
273
 
264
- def _show_warning(self, warning):
274
+ def _show_warning(self, warning: str) -> None:
265
275
  show_warning(warning)
266
276
 
267
- def _trans(self, text, **kwargs):
277
+ def _trans(self, text: str, **kwargs) -> str:
268
278
  return trans._(text, **kwargs)
269
279
 
270
280
 
271
- if __name__ == "__main__":
281
+ if __name__ == '__main__':
272
282
  from qtpy.QtWidgets import QApplication
273
283
 
274
284
  app = QApplication([])
@@ -1,3 +1,5 @@
1
+ import textwrap
2
+
1
3
  from qtpy.QtWidgets import QDialog, QLabel, QPushButton, QVBoxLayout, QWidget
2
4
 
3
5
 
@@ -7,13 +9,13 @@ class RestartWarningDialog(QDialog):
7
9
  self.setWindowTitle('Restart napari')
8
10
  okay_btn = QPushButton('Okay')
9
11
  self.restart_warning_text = """
10
- Plugins have been installed or uninstalled. If you notice any
11
- issues with plugin functionality, you may need to restart napari.
12
+ Plugins have been added/removed or updated. If you notice any issues
13
+ with plugin functionality, you may need to restart napari.
12
14
  """
13
15
 
14
16
  okay_btn.clicked.connect(self.accept)
15
17
 
16
18
  layout = QVBoxLayout()
17
- layout.addWidget(QLabel(self.restart_warning_text))
19
+ layout.addWidget(QLabel(textwrap.dedent(self.restart_warning_text)))
18
20
  layout.addWidget(okay_btn)
19
21
  self.setLayout(layout)
@@ -1,14 +1,14 @@
1
1
  from qtpy.QtCore import Signal
2
2
  from qtpy.QtGui import QMouseEvent
3
- from qtpy.QtWidgets import QLabel
3
+ from qtpy.QtWidgets import QLabel, QWidget
4
4
 
5
5
 
6
6
  class ClickableLabel(QLabel):
7
7
  clicked = Signal()
8
8
 
9
- def __init__(self, parent=None):
9
+ def __init__(self, parent: QWidget | None = None) -> None:
10
10
  super().__init__(parent=parent)
11
11
 
12
- def mouseReleaseEvent(self, event: QMouseEvent):
12
+ def mouseReleaseEvent(self, event: QMouseEvent) -> None:
13
13
  super().mouseReleaseEvent(event)
14
14
  self.clicked.emit()
@@ -1,5 +1,5 @@
1
1
  /* ------------ Plugin Dialog ------------ */
2
- /*
2
+ /*
3
3
 
4
4
  To be able to use this custom qss, we must use the `get_current_stylesheet` helper that napari provides.
5
5
  By using that function we can replace the variables that are used in this stylesheet, e.g. `foreground`.
@@ -11,15 +11,26 @@ from napari._qt.qt_resources import get_current_stylesheet
11
11
  ```
12
12
 
13
13
  */
14
+
15
+ QLineEdit {
16
+ border: 1px solid white;
17
+ font-size: {{ increase(font_size, 2) }};
18
+ }
19
+
20
+ QLineEdit:focus {
21
+ border: 1px solid {{ current }};
22
+ }
23
+
14
24
  QCollapsible#install_info_button {
15
25
  background-color: {{ darken(foreground, 20) }};
16
26
  color: {{ darken(text, 15) }};
27
+ font-size: {{ font_size }};
17
28
  }
18
- QWidget#info_widget {
29
+ QWidget#info_widget, QWidget#info_widget > QLabel {
19
30
  background-color: {{ darken(foreground, 20) }};
20
31
  margin: 0px;
21
32
  padding: 0px;
22
- font: 11px;
33
+ font-size: {{ font_size }};
23
34
  }
24
35
 
25
36
  QLabel#author_text {
@@ -30,6 +41,9 @@ QElidingLabel#summary_text {
30
41
  color: {{ darken(text, 35) }};
31
42
  }
32
43
 
44
+ QLabel#available_message {
45
+ background-color: {{ console }};
46
+ }
33
47
 
34
48
  QLabel#install_choice {
35
49
  background-color: {{ current }};
@@ -56,7 +70,7 @@ QWidget#install_choice_widget {
56
70
  color: {{ darken(text, 35) }};
57
71
  margin: 0px;
58
72
  padding: 0px;
59
- font: 11px;
73
+ font-size: {{ font_size }};
60
74
  }
61
75
 
62
76
  QPluginList {
@@ -82,19 +96,19 @@ PluginListItem QCheckBox::indicator:disabled {
82
96
  image: url("theme_{{ id }}:/check_50.svg");
83
97
  }
84
98
 
85
- QPushButton#install_button {
99
+ QPushButton#install_button, QPushButton#refresh_button {
86
100
  background-color: {{ current }}
87
101
  }
88
102
 
89
- QPushButton#install_button:hover {
103
+ QPushButton#install_button:hover, QPushButton#refresh_button:hover {
90
104
  background-color: {{ lighten(current, 10) }}
91
105
  }
92
106
 
93
- QPushButton#install_button:pressed {
107
+ QPushButton#install_button:pressed, QPushButton#refresh_button:pressed {
94
108
  background-color: {{ darken(current, 10) }}
95
109
  }
96
110
 
97
- QPushButton#install_button:disabled {
111
+ QPushButton#install_button:disabled, QPushButton#refresh_button:disabled {
98
112
  background-color: {{ lighten(current, 20) }}
99
113
  }
100
114
 
@@ -130,10 +144,6 @@ QPushButton#close_button:disabled {
130
144
  background-color: {{ lighten(secondary, 10) }}
131
145
  }
132
146
 
133
- QPushButton#refresh_button:disabled {
134
- background-color: {{ lighten(secondary, 10) }}
135
- }
136
-
137
147
  #small_text {
138
148
  color: {{ opacity(text, 150) }};
139
149
  font-size: {{ decrease(font_size, 2) }};
@@ -215,6 +225,13 @@ QtPluginDialog QSplitter{
215
225
  padding-right: 2;
216
226
  }
217
227
 
228
+ QtPluginDialog QSplitter::handle {
229
+ width: 4px;
230
+ height: 4px;
231
+ border: none;
232
+ background-color: {{ background }};
233
+ image: url("theme_{{ id }}:/horizontal_separator.svg");
234
+ }
218
235
 
219
236
  QtPluginSorter {
220
237
  padding: 20px;
@@ -355,7 +372,7 @@ QToolButton {
355
372
  background-color: {{ darken(foreground, 20) }};
356
373
  color: {{ darken(text, 15) }};
357
374
  padding: 3 12px;
358
- font: 14px;
375
+ font-size: {{ increase(font_size, 2) }};
359
376
  }
360
377
 
361
378
  QToolButton:hover {
@@ -17,8 +17,8 @@ def is_conda_package(pkg: str, prefix: str | None = None) -> bool:
17
17
  # saved within a ``conda-meta`` folder within the given environment of interest.
18
18
  conda_meta_dir = Path(prefix or sys.prefix) / 'conda-meta'
19
19
  return any(
20
- re.match(rf"{pkg}-[^-]+-[^-]+.json", p.name)
21
- for p in conda_meta_dir.glob(f"{pkg}-*-*.json")
20
+ re.match(rf'{pkg}-[^-]+-[^-]+.json', p.name)
21
+ for p in conda_meta_dir.glob(f'{pkg}-*-*.json')
22
22
  )
23
23
 
24
24
 
@@ -29,7 +29,7 @@ def normalize_label(label: str) -> str:
29
29
  https://packaging.python.org/en/latest/specifications/well-known-project-urls/#label-normalization
30
30
  """
31
31
  chars_to_remove = string.punctuation + string.whitespace
32
- removal_map = str.maketrans("", "", chars_to_remove)
32
+ removal_map = str.maketrans('', '', chars_to_remove)
33
33
  return label.translate(removal_map).lower()
34
34
 
35
35
 
@@ -1,45 +1,15 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: napari-plugin-manager
3
- Version: 0.1.6
3
+ Version: 0.1.7
4
4
  Summary: Install plugins for napari, in napari.
5
5
  Author-email: napari team <napari-steering-council@googlegroups.com>
6
- License: BSD 3-Clause License
7
-
8
- Copyright (c) 2018, Napari
9
- All rights reserved.
10
-
11
- Redistribution and use in source and binary forms, with or without
12
- modification, are permitted provided that the following conditions are met:
13
-
14
- * Redistributions of source code must retain the above copyright notice, this
15
- list of conditions and the following disclaimer.
16
-
17
- * Redistributions in binary form must reproduce the above copyright notice,
18
- this list of conditions and the following disclaimer in the documentation
19
- and/or other materials provided with the distribution.
20
-
21
- * Neither the name of the copyright holder nor the names of its
22
- contributors may be used to endorse or promote products derived from
23
- this software without specific prior written permission.
24
-
25
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
29
- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31
- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32
- CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
33
- OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35
-
6
+ License-Expression: BSD-3-Clause
36
7
  Project-URL: homepage, https://github.com/napari/napari-plugin-manager
37
8
  Classifier: Development Status :: 3 - Alpha
38
9
  Classifier: Environment :: X11 Applications :: Qt
39
10
  Classifier: Framework :: napari
40
11
  Classifier: Intended Audience :: Education
41
12
  Classifier: Intended Audience :: Science/Research
42
- Classifier: License :: OSI Approved :: BSD License
43
13
  Classifier: Programming Language :: C
44
14
  Classifier: Programming Language :: Python
45
15
  Classifier: Programming Language :: Python :: 3 :: Only
@@ -59,6 +29,7 @@ Classifier: Operating System :: MacOS
59
29
  Requires-Python: >=3.10
60
30
  Description-Content-Type: text/markdown
61
31
  License-File: LICENSE
32
+ Requires-Dist: napari
62
33
  Requires-Dist: npe2
63
34
  Requires-Dist: qtpy
64
35
  Requires-Dist: superqt
@@ -67,11 +38,14 @@ Requires-Dist: packaging
67
38
  Provides-Extra: dev
68
39
  Requires-Dist: PyQt6; extra == "dev"
69
40
  Requires-Dist: pre-commit; extra == "dev"
41
+ Provides-Extra: uv
42
+ Requires-Dist: uv; extra == "uv"
70
43
  Provides-Extra: testing
44
+ Requires-Dist: napari-plugin-manager[uv]; extra == "testing"
71
45
  Requires-Dist: coverage; extra == "testing"
72
46
  Requires-Dist: flaky; extra == "testing"
73
47
  Requires-Dist: pytest; extra == "testing"
74
- Requires-Dist: pytest-qt; extra == "testing"
48
+ Requires-Dist: pytest-qt<4.5; extra == "testing"
75
49
  Requires-Dist: virtualenv; extra == "testing"
76
50
  Provides-Extra: docs
77
51
  Requires-Dist: sphinx>6; extra == "docs"
@@ -102,7 +76,7 @@ The `napari-plugin-manager` used to be part of the [napari] codebase before the
102
76
  series. It's now maintained as a separate project and package to allow uncoupled iterations outside
103
77
  of the `napari` release cycle.
104
78
 
105
- Future work will allow other applications with a plugin ecosytem to customize and
79
+ Future work will allow other applications with a plugin ecosytem to customize and
106
80
  use the `plugin-manager`. This package remains under active development and contributions
107
81
  are very welcome. Please [open an issue] to discuss potential improvements.
108
82
 
@@ -191,7 +165,7 @@ a restart to be properly configured.
191
165
 
192
166
  ### Installing a plugin via direct entry
193
167
 
194
- You can also install a napari plugin or any other package via the direct entry option. The following steps
168
+ You can also install a napari plugin or any other package via the direct entry option. The following steps
195
169
  correspond to the options and buttons located at the **bottom of the dialog**.
196
170
 
197
171
  1. You can type either the name of the package, a url to the resource or drag and drop a compressed file
@@ -0,0 +1,23 @@
1
+ napari_plugin_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ napari_plugin_manager/_version.py,sha256=szvPIs2C82UunpzuvVg3MbF4QhzbBYTsVJ8DmPfq6_E,704
3
+ napari_plugin_manager/base_qt_package_installer.py,sha256=rWsD1BvJL3RG9pBEJEaUH5ugGzg4sVgQVg0RHKnP6us,24487
4
+ napari_plugin_manager/base_qt_plugin_dialog.py,sha256=0NDzTN7Bxek5mr4DZDPJVddh1eDjIwZtUxeKFSCQToA,67432
5
+ napari_plugin_manager/npe2api.py,sha256=gAPOC-g0GWAwN71m0GimM0SW6YHI39XxSJm_qhq3-OY,4352
6
+ napari_plugin_manager/qt_package_installer.py,sha256=QFQDED3MKbQupKF7OjBPz70cK2zrgIP2gu4vdUVV8Tk,3511
7
+ napari_plugin_manager/qt_plugin_dialog.py,sha256=8GcaQuSWF5jZHcdn6j2Ye6liJ5yRDjtnuqenpVSyfkM,10208
8
+ napari_plugin_manager/qt_warning_dialog.py,sha256=DtPoFBn7zDfSmkdMokm1BcuoYasngkC0jwJok-oIuGk,727
9
+ napari_plugin_manager/qt_widgets.py,sha256=OatVQPuJFP5sgYRq_KiaynwXI3UfLGiTwBRlFy-b5mk,399
10
+ napari_plugin_manager/styles.qss,sha256=2oJBNiLT3YtqQP3avQGAOWcSSOZiFHGDsHtI5TjjxuA,7928
11
+ napari_plugin_manager/utils.py,sha256=vGvOndyiwc_JaSHVtXIc9z-dGsewo_vRb31U-26vy24,2247
12
+ napari_plugin_manager/_tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
+ napari_plugin_manager/_tests/conftest.py,sha256=Bm8u6hT5-mQXaxamke79tJGrU8BZA3V444YBLPivVr8,1885
14
+ napari_plugin_manager/_tests/test_base_installer_process.py,sha256=Cv-nBnUeNAX6pYUE1zs38I9vGtCE-ahBN4q-xcBH-pw,561
15
+ napari_plugin_manager/_tests/test_installer_process.py,sha256=CshbV0OGzmL0kus9_0AvrEOU_vleMdSmPPo0RbCizMw,12760
16
+ napari_plugin_manager/_tests/test_npe2api.py,sha256=ncBGWHrA5uZjmt6w4lVlx8D-n_3At1bfAZgkMRxK7Lg,1275
17
+ napari_plugin_manager/_tests/test_qt_plugin_dialog.py,sha256=4zGIfLomCCC-rTebkf6ggXd8Tedx6mi7GtmRv6IKTj4,21670
18
+ napari_plugin_manager/_tests/test_utils.py,sha256=rAlqp8y1MR3U4nWCN1jekbvP_avket3fVgEQwJDqpKk,1674
19
+ napari_plugin_manager-0.1.7.dist-info/licenses/LICENSE,sha256=8dAlKbOqTMYe9L-gL_kEx5Xr1Sd0AbaWQDUkpiOp3vI,1506
20
+ napari_plugin_manager-0.1.7.dist-info/METADATA,sha256=pFSZqqw0ZV6XX4mCW2h0mUdzQF_-YIhzTxAJwXzhuYE,12181
21
+ napari_plugin_manager-0.1.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
22
+ napari_plugin_manager-0.1.7.dist-info/top_level.txt,sha256=pmCqLetuumhY1CKSuTZ5eQsitzazrSvc7V_mkugEPTY,22
23
+ napari_plugin_manager-0.1.7.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.0.1)
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,23 +0,0 @@
1
- napari_plugin_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- napari_plugin_manager/_version.py,sha256=ESbJO0YD7TYfOUv_WDIJJgWELGepEWsoyhqVifEcXPA,511
3
- napari_plugin_manager/base_qt_package_installer.py,sha256=Nw6EIjZOmKVrJJCQrb1TjUMVeey4WIbib6hzBXMcSBc,21857
4
- napari_plugin_manager/base_qt_plugin_dialog.py,sha256=nLqOJs_kUdGmmlTjaQRCu-EWB-4smwjbHlYpoSJ5jZs,66093
5
- napari_plugin_manager/npe2api.py,sha256=KtfV-fspfADxSHMD_AoBaRt2WFkfeZ-W4aRl0SLyna8,4367
6
- napari_plugin_manager/qt_package_installer.py,sha256=j-pacW6wHVq3iJaZXsj6D-_VH25Fz-55r7clcd_CQvE,2804
7
- napari_plugin_manager/qt_plugin_dialog.py,sha256=Ig4TtjCh9Z2Dx_QpiOsfLlgolPJHmJ5_7VuTU2DE0Ag,9607
8
- napari_plugin_manager/qt_warning_dialog.py,sha256=ue4CeMptlBBkBctPg7qCayamrkm75iLqASSFUvwo_Bc,669
9
- napari_plugin_manager/qt_widgets.py,sha256=O8t5CbN8r_16cQzshyjvhTEYdUcj7OX0-bfYIiN2uSs,356
10
- napari_plugin_manager/styles.qss,sha256=9ODPba2IorJybWObWoEO9VGq4AO0IYlAa8brN14tgZU,7379
11
- napari_plugin_manager/utils.py,sha256=u0OSzNbSTyk7a-NdwGfrqry_q94GiHfKQnWB20r6V9A,2247
12
- napari_plugin_manager/_tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
- napari_plugin_manager/_tests/conftest.py,sha256=OvzenfBP2oIS6x8ksr9FhPXdsLV3Q_3Kzr6PRJe45Uc,1885
14
- napari_plugin_manager/_tests/test_base_installer_process.py,sha256=Cv-nBnUeNAX6pYUE1zs38I9vGtCE-ahBN4q-xcBH-pw,561
15
- napari_plugin_manager/_tests/test_installer_process.py,sha256=qPSDcYWPQ08gzM38av2tcE9XCtruHv-Mo6duQ0sZp-8,11614
16
- napari_plugin_manager/_tests/test_npe2api.py,sha256=nf3UG68gqoCFyiPDisToZsLpZG0uvzGUUk8H6Fy3dqE,1248
17
- napari_plugin_manager/_tests/test_qt_plugin_dialog.py,sha256=IRXodt3IrE7rXHZO0R69lhz4_2mMW3MOE9LLQ5tCxWY,21727
18
- napari_plugin_manager/_tests/test_utils.py,sha256=I9rYJV_JVKg6GeBlhY4A_6aY1N5MbM7jgNz5wewiWIQ,1669
19
- napari_plugin_manager-0.1.6.dist-info/licenses/LICENSE,sha256=8dAlKbOqTMYe9L-gL_kEx5Xr1Sd0AbaWQDUkpiOp3vI,1506
20
- napari_plugin_manager-0.1.6.dist-info/METADATA,sha256=HQvATPh6tVJmaZBlNTG9BmG488v4ATn6OoposuwN4zE,13810
21
- napari_plugin_manager-0.1.6.dist-info/WHEEL,sha256=ooBFpIzZCPdw3uqIQsOo4qqbA4ZRPxHnOH7peeONza0,91
22
- napari_plugin_manager-0.1.6.dist-info/top_level.txt,sha256=pmCqLetuumhY1CKSuTZ5eQsitzazrSvc7V_mkugEPTY,22
23
- napari_plugin_manager-0.1.6.dist-info/RECORD,,