Skip to content

Commit

Permalink
Merge pull request #17 from PyMoDAQ/patch_version_and_print
Browse files Browse the repository at this point in the history
Patch version and print
  • Loading branch information
seb5g authored Nov 8, 2023
2 parents 0586fa7 + 06c719d commit 4ccf506
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 41 deletions.
3 changes: 1 addition & 2 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
include README.rst
include LICENSE
include src/pymodaq_plugin_manager/data/*.json
include src/pymodaq_plugin_manager/data/*.schema
graft src
include /doc/*.md
include icon.ico
2 changes: 1 addition & 1 deletion src/pymodaq_plugin_manager/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.1.0
1.2.0
5 changes: 3 additions & 2 deletions src/pymodaq_plugin_manager/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
from pathlib import Path
base_path = Path(__file__).parent

with open(str(base_path.joinpath('data/PluginList.json'))) as f:
__version__ = json.load(f)['version']
with open(str(Path(__file__).parent.joinpath('VERSION')), 'r') as fvers:
__version__ = fvers.read().strip()

70 changes: 51 additions & 19 deletions src/pymodaq_plugin_manager/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,19 @@ def setTextFilter(self, regexp):
self.invalidateFilter()


class PluginFetcher(QtCore.QObject):

plugins_signal = QtCore.Signal(tuple)

def __init__(self, print_method=logger.info):
super().__init__()
self.print_method = print_method

def fetch_plugins(self):
self.plugins_signal.emit(get_plugins(False, pymodaq_version=get_pymodaq_version(),
print_method=self.print_method))


class PluginManager(QtCore.QObject):
"""Main UI to display a list of plugins and install/uninstall them
Expand All @@ -114,10 +127,17 @@ def __init__(self, parent, standalone=False):
self.parent.setLayout(QtWidgets.QVBoxLayout())
self.standalone = standalone

self.plugins_available, self.plugins_installed,\
self.plugins_update = get_plugins(False, pymodaq_version=get_pymodaq_version())

self.setup_UI()
self.enable_ui(False)

self.plugin_thread = QtCore.QThread()
plugin_fetcher = PluginFetcher(self.print_info)
plugin_fetcher.plugins_signal.connect(self.setup_models)
plugin_fetcher.moveToThread(self.plugin_thread)
self.plugin_thread.plugin_fetcher = plugin_fetcher
self.plugin_thread.started.connect(plugin_fetcher.fetch_plugins)

self.plugin_thread.start()

def check_version(self, show=True):
try:
Expand Down Expand Up @@ -158,6 +178,11 @@ def restart(self):
else:
self.restart_signal.emit()

def enable_ui(self, enable=True):
self.check_updates_pb.setEnabled(enable)
self.plugin_choice.setEnabled(enable)
self.search_edit.setEnabled(enable)

def setup_UI(self):

settings_widget = QtWidgets.QWidget()
Expand Down Expand Up @@ -202,6 +227,18 @@ def setup_UI(self):
self.table_view.horizontalHeader().show()
self.table_view.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.ResizeToContents)

self.info_widget = QtWidgets.QTextEdit()
self.info_widget.setReadOnly(True)

splitter.addWidget(self.table_view)
splitter.addWidget(self.info_widget)

self.parent.layout().addWidget(splitter)
QtWidgets.QApplication.processEvents()

def setup_models(self, plugins: tuple):
self.plugins_available, self.plugins_installed, self.plugins_update = plugins

self.model_available = TableModel([[plugin['display-name'],
plugin['version']] for plugin in self.plugins_available],
header=['Plugin', 'Version'],
Expand All @@ -224,14 +261,7 @@ def setup_UI(self):
self.table_view.setModel(model_available_proxy)
self.table_view.setSortingEnabled(True)
self.table_view.clicked.connect(self.item_clicked)

self.info_widget = QtWidgets.QTextEdit()
self.info_widget.setReadOnly(True)

splitter.addWidget(self.table_view)
splitter.addWidget(self.info_widget)

self.parent.layout().addWidget(splitter)
self.enable_ui(True)

def do_action(self):
indexes_plugin = []
Expand Down Expand Up @@ -295,18 +325,20 @@ def do_action(self):
elif msgBox.clickedButton() is restart_button:
self.restart()

def print_info(self, message: str):
self.info_widget.moveCursor(QTextCursor.End)
self.info_widget.insertPlainText(f'{message}\n')
self.info_widget.moveCursor(QTextCursor.End)
QtCore.QThread.msleep(100)
QtWidgets.QApplication.processEvents()

def do_subprocess(self, command):
try:
self.info_widget.moveCursor(QTextCursor.End)
self.info_widget.insertPlainText(' '.join(command))
self.info_widget.moveCursor(QTextCursor.End)
self.print_info(' '.join(command))

with subprocess.Popen(command, stdout=subprocess.PIPE, universal_newlines=True, shell=True) as sp:
while True:
self.info_widget.moveCursor(QTextCursor.End)
self.info_widget.insertPlainText(sp.stdout.readline())
self.info_widget.moveCursor(QTextCursor.End)
QtWidgets.QApplication.processEvents()
self.print_info(sp.stdout.readline())
return_code = sp.poll()
if return_code is not None:
self.info_widget.insertPlainText(str(return_code))
Expand Down Expand Up @@ -388,8 +420,8 @@ def main():
win.setWindowTitle('PyMoDAQ Plugin Manager')
widget = QtWidgets.QWidget()
win.setCentralWidget(widget)
prog = PluginManager(widget, standalone=True)
win.show()
prog = PluginManager(widget, standalone=True)
sys.exit(app.exec_())


Expand Down
43 changes: 26 additions & 17 deletions src/pymodaq_plugin_manager/validate.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,32 +47,33 @@ def find_dict_in_list_from_key_val(dicts, key, value):
return None


def get_pypi_package_list(match_name: str = None) -> List[str]:
def get_pypi_package_list(match_name: str = None, print_method=logger.info) -> List[str]:
"""Connect to the "simple" pypi url to get the list of all packages matching all or part of
the given name
Parameters
----------
match_name: str
The package name to be (partially) matched
print_method: Callable
Examples
--------
get_pypi_package_list('pymodaq_plugins') will retrieve the names of all packages having 'pymodaq_plugins'
in their name
"""
status = 'Connecting to the pypi repository, may take some time to retrieve the list'
logger.info(status)
print_method(status)
simple_package = requests.get('https://pypi.org/simple/')
if simple_package.status_code == 503:
info = 'The service from pypi is currently unavailable, please retry later or install your plugins manually'
logger.info(info)
print_method(info)
tree = html.fromstring(simple_package.text)
packages = []
for child in tree.body:
if match_name is None or match_name in child.text:
packages.append(child.text)
logger.info(f'Got package {child.text}')
print_method(f'Got package {child.text}')
return packages


Expand Down Expand Up @@ -164,7 +165,8 @@ def get_pypi_pymodaq(package_name='pymodaq-plugins', pymodaq_version: Version =
return get_metadata_from_json(latest)


def get_pypi_plugins(browse_pypi=True, pymodaq_version: Union[Version, str] = None) -> List[dict]:
def get_pypi_plugins(browse_pypi=True, pymodaq_version: Union[Version, str] = None,
print_method=logger.info) -> List[dict]:
"""Fetch the list of plugins (for a given version) of pymodaq
Parameters
Expand All @@ -173,16 +175,18 @@ def get_pypi_plugins(browse_pypi=True, pymodaq_version: Union[Version, str] = No
If True get the list from pypi server, if False from the builtin json (deprecated, should be True)
pymodaq_version: Union[str, Version]
a given pymodaq version (or the latest if None)
print_method: Callable
a callable accepting str argument
Returns
-------
list of dictionaries giving info on plugins
"""
plugins = []
packages = get_pypi_package_list('pymodaq-plugins')
packages = get_pypi_package_list('pymodaq-plugins', print_method=print_method)
pymodaq_latest = Version(get_pypi_pymodaq('pymodaq')['version'])
for package in packages:
logger.info(f'Fetching metadata for package {package}')
print_method(f'Fetching metadata for package {package}')
metadata = get_pypi_pymodaq(package, pymodaq_version, pymodaq_latest)
if metadata is not None:
title = metadata['description'].split('\n')[0]
Expand Down Expand Up @@ -232,26 +236,31 @@ def get_check_repo(plugin_dict):
logger.info(f'SHA256 is Ok')


def get_plugins(from_json=False, browse_pypi=True, pymodaq_version: Version = None):
def get_plugins(from_json=False, browse_pypi=True, pymodaq_version: Version = None, print_method=logger.info):
"""get PyMoDAQ plugins
Parameters
----------
from_json: (bool) if True get the plugins list and source files from the json data file (deprecated) else from the pypi
server
browse_pypi: (bool) if from_json is False:
if True get the list of plugins name from the https://pypi.org/simple/ website, then get the sources from the pypi
server
if False, get the list of plugins name from the json data, then fetch the source from the pypi server
from_json: bool
if True get the plugins list and source files from the json data file (deprecated) else from the pypi server
browse_pypi: bool
if from_json is False:
if True get the list of plugins name from the https://pypi.org/simple/ website, then get the sources from
the pypiserver
if False, get the list of plugins name from the json data, then fetch the source from the pypi server
pymodaq_version: Version
the current version of PyMoDAQ
print_method: Callable
a callable accepting string
Returns
-------
plugins_available: list of available plugins for installation
plugins_installed: list of already installed plugins
plugins_update: list of plugins with existing update
"""
logger.info('Fetching plugin list')
plugins_available = get_pypi_plugins(browse_pypi=browse_pypi, pymodaq_version=pymodaq_version)
print_method('Fetching plugin list')
plugins_available = get_pypi_plugins(browse_pypi=browse_pypi, pymodaq_version=pymodaq_version,
print_method=print_method)

plugins = deepcopy(plugins_available)
plugins_installed_init = [{'plugin-name': entry.module_name,
Expand Down

0 comments on commit 4ccf506

Please sign in to comment.