scipion-pyworkflow 3.10.6__py3-none-any.whl → 3.11.1__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.
Files changed (57) hide show
  1. pyworkflow/config.py +131 -67
  2. pyworkflow/constants.py +2 -1
  3. pyworkflow/gui/browser.py +39 -5
  4. pyworkflow/gui/dialog.py +2 -0
  5. pyworkflow/gui/form.py +141 -52
  6. pyworkflow/gui/gui.py +8 -8
  7. pyworkflow/gui/project/project.py +6 -7
  8. pyworkflow/gui/project/searchprotocol.py +91 -7
  9. pyworkflow/gui/project/viewdata.py +1 -1
  10. pyworkflow/gui/project/viewprotocols.py +45 -22
  11. pyworkflow/gui/project/viewprotocols_extra.py +9 -6
  12. pyworkflow/gui/widgets.py +2 -2
  13. pyworkflow/mapper/sqlite.py +4 -4
  14. pyworkflow/plugin.py +93 -44
  15. pyworkflow/project/project.py +158 -70
  16. pyworkflow/project/usage.py +165 -0
  17. pyworkflow/protocol/executor.py +30 -18
  18. pyworkflow/protocol/hosts.py +9 -6
  19. pyworkflow/protocol/launch.py +15 -8
  20. pyworkflow/protocol/params.py +59 -19
  21. pyworkflow/protocol/protocol.py +124 -58
  22. pyworkflow/resources/showj/arrowDown.png +0 -0
  23. pyworkflow/resources/showj/arrowUp.png +0 -0
  24. pyworkflow/resources/showj/background_section.png +0 -0
  25. pyworkflow/resources/showj/colRowModeOff.png +0 -0
  26. pyworkflow/resources/showj/colRowModeOn.png +0 -0
  27. pyworkflow/resources/showj/delete.png +0 -0
  28. pyworkflow/resources/showj/doc_icon.png +0 -0
  29. pyworkflow/resources/showj/download_icon.png +0 -0
  30. pyworkflow/resources/showj/enabled_gallery.png +0 -0
  31. pyworkflow/resources/showj/galleryViewOff.png +0 -0
  32. pyworkflow/resources/showj/galleryViewOn.png +0 -0
  33. pyworkflow/resources/showj/goto.png +0 -0
  34. pyworkflow/resources/showj/menu.png +0 -0
  35. pyworkflow/resources/showj/separator.png +0 -0
  36. pyworkflow/resources/showj/tableViewOff.png +0 -0
  37. pyworkflow/resources/showj/tableViewOn.png +0 -0
  38. pyworkflow/resources/showj/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  39. pyworkflow/resources/showj/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  40. pyworkflow/resources/showj/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  41. pyworkflow/resources/showj/volumeOff.png +0 -0
  42. pyworkflow/resources/showj/volumeOn.png +0 -0
  43. pyworkflow/utils/log.py +15 -6
  44. pyworkflow/utils/properties.py +78 -92
  45. pyworkflow/utils/utils.py +3 -2
  46. pyworkflow/viewer.py +23 -1
  47. pyworkflow/webservices/config.py +0 -3
  48. pyworkflow/webservices/notifier.py +24 -34
  49. pyworkflowtests/protocols.py +1 -3
  50. pyworkflowtests/tests/test_protocol_execution.py +4 -0
  51. {scipion_pyworkflow-3.10.6.dist-info → scipion_pyworkflow-3.11.1.dist-info}/METADATA +13 -27
  52. {scipion_pyworkflow-3.10.6.dist-info → scipion_pyworkflow-3.11.1.dist-info}/RECORD +56 -35
  53. {scipion_pyworkflow-3.10.6.dist-info → scipion_pyworkflow-3.11.1.dist-info}/WHEEL +1 -1
  54. scipion_pyworkflow-3.10.6.dist-info/dependency_links.txt +0 -1
  55. {scipion_pyworkflow-3.10.6.dist-info → scipion_pyworkflow-3.11.1.dist-info}/entry_points.txt +0 -0
  56. {scipion_pyworkflow-3.10.6.dist-info → scipion_pyworkflow-3.11.1.dist-info}/licenses/LICENSE.txt +0 -0
  57. {scipion_pyworkflow-3.10.6.dist-info → scipion_pyworkflow-3.11.1.dist-info}/top_level.txt +0 -0
pyworkflow/utils/log.py CHANGED
@@ -82,9 +82,9 @@ class LoggingConfigurator:
82
82
  customLoggingActive = False # Holds if a custom logging configuration has taken place.
83
83
 
84
84
  @classmethod
85
- def setupLogging(cls, logFile=None, console=True):
85
+ def setupLogging(cls, logFile=None, console=True, consoleLevel='ERROR'):
86
86
  if not cls.loadCustomLoggingConfig():
87
- cls.setupDefaultLogging(logFile=logFile, console=console)
87
+ cls.setupDefaultLogging(logFile=logFile, console=console, consoleLevel=consoleLevel)
88
88
 
89
89
  @classmethod
90
90
  def loadCustomLoggingConfig(cls):
@@ -104,13 +104,13 @@ class LoggingConfigurator:
104
104
  return False
105
105
 
106
106
  @staticmethod
107
- def setupDefaultLogging(logFile=None, console=True):
107
+ def setupDefaultLogging(logFile=None, console=True, consoleLevel="ERROR"):
108
108
  """ Configures logging in a default way that is to file (rotating) and console
109
109
 
110
110
  :param logFile: Optional, path to the log file. Defaults to SCIPION_LOG variable value. If folder
111
- does not exists it will be created.
111
+ does not exist it will be created.
112
112
  :param console: Optional, defaults to True, so log messages are sent to the terminal as well
113
-
113
+ :param consoleLevel: Optional, defaults to ERROR. Only error messages are sent to the console.
114
114
  """
115
115
  from pyworkflow import Config
116
116
 
@@ -147,7 +147,7 @@ class LoggingConfigurator:
147
147
 
148
148
  if console:
149
149
  config["handlers"][CONSOLE_HANDLER] = {
150
- 'level': 'ERROR', #Config.SCIPION_LOG_LEVEL,
150
+ 'level': consoleLevel,
151
151
  'class': 'logging.StreamHandler',
152
152
  'formatter': 'standard',
153
153
  }
@@ -282,3 +282,12 @@ def getExtraLogInfo(measurement, status, project_name=None, prot_id=None, prot_n
282
282
 
283
283
  except Exception as e:
284
284
  print("getExtraLogInfo failed: %s.Params were: dbFilename %s" % (e, dbfilename))
285
+
286
+
287
+ def changeLogLevel(newLoglevel):
288
+ """ Changes "on-the-fly" the log level iterating through the handlders"""
289
+
290
+ logger = logging.getLogger()
291
+ logger.setLevel(newLoglevel)
292
+ for handler in logger.handlers:
293
+ handler.setLevel(newLoglevel)
@@ -121,11 +121,8 @@ class Message:
121
121
  LABEL_RUNNAME = 'Run name'
122
122
  LABEL_EXECUTION = 'Run mode'
123
123
  LABEL_RUNMODE = 'Mode'
124
- LABEL_PARALLEL = 'Parallel'
124
+ LABEL_PARALLEL = 'Program compute'
125
125
  LABEL_HOST = 'Host'
126
- LABEL_THREADS = 'Threads'
127
- LABEL_SCIPION_THREADS = 'Scipion threads'
128
- LABEL_MPI = 'MPI'
129
126
  LABEL_QUEUE = 'Use a queue engine?'
130
127
 
131
128
  LABEL_WAIT_FOR = 'Wait for'
@@ -144,17 +141,6 @@ will clean the whole run directory and start from scratch.
144
141
  """
145
142
 
146
143
  HELP_PARALLEL_HEADER = 'Define the number of processors to be used in the execution.\nCheck %s for more detailed info.\n\n' % DOCSITEURLS.THREADS_MPIS_AND_GPUS
147
- HELP_PARALLEL_MPI = ("*MPI*:\nThis is a number of independent processes"
148
- " that communicate through message passing "
149
- "over the network (or the same computer).\n")
150
- HELP_PARALLEL_THREADS = ("*Threads*:\nThis refers to different execution threads in the same process that "
151
- "can share memory. They run in the same computer. This value is an argument"
152
- " passed to the program integrated")
153
-
154
- HELP_SCIPION_THREADS = ("*Scipion threads*:\n threads created by Scipion to run the steps."
155
- " 1 thread is always used by the master/main process. Then extra threads will allow"
156
- " this protocol to run several steps at the same time, taking always into account "
157
- "restrictions to previous steps and 'theoretical GPU availability'")
158
144
 
159
145
  HELP_USEQUEUE = """
160
146
  Click Yes if you want to send this execution to a queue engine like Slurm, Torque, ...
@@ -478,54 +464,54 @@ class Sprite:
478
464
  # To get font awesome icons into png use: http://fa2png.io/
479
465
  class Icon:
480
466
  # Protocols status
481
- PROT_DISABLED = SpriteImage(16,32,'prot_disabled.png',bottom=32,right=64)
482
- BETA = SpriteImage(0,0,'beta.png',bottom=16,right=32)
483
- NEW = SpriteImage(32,0,'new.png',bottom=48,right=32)
484
- PRODUCTION = SpriteImage(32,32,'production.png',bottom=48,right=64)
485
- UPDATED = SpriteImage(16,0,'updated.png',bottom=32,right=32)
486
-
487
- GROUP = SpriteImage(80, 224,'class_obj.png')
488
- FAVORITE = SpriteImage(80,256,'bookmark.png')
489
- DEBUG = SpriteImage(64,288,'debug.png')
490
- DOWNLOAD = SpriteImage(48,272,'fa-download.png')
491
- FIND = SpriteImage(80,272,'binoculares.png')
492
- SELECT_ALL = SpriteImage(0,32,'workflow.png')
467
+ PROT_DISABLED = SpriteImage(16,32, 'prot_disabled.png', bottom=32, right=64)
468
+ BETA = SpriteImage(0, 0, 'beta.png', bottom=16, right=32)
469
+ NEW = SpriteImage(32, 0, 'new.png', bottom=48, right=32)
470
+ PRODUCTION = SpriteImage(32, 32, 'production.png', bottom=48, right=64)
471
+ UPDATED = SpriteImage(16, 0, 'updated.png', bottom=32, right=32)
472
+
473
+ GROUP = SpriteImage(80, 224, 'class_obj.png')
474
+ FAVORITE = SpriteImage(80, 256, 'bookmark.png')
475
+ DEBUG = SpriteImage(64, 288, 'debug.png')
476
+ DOWNLOAD = SpriteImage(48, 272, 'fa-download.png')
477
+ FIND = SpriteImage(80, 272, 'binoculares.png')
478
+ SELECT_ALL = SpriteImage(0, 32, 'workflow.png')
493
479
 
494
480
  # Project window icons
495
- RUNS_TREE = SpriteImage(16,272,'fa-sitemap.png')
496
- ACTION_NEW = SpriteImage(80,304,'fa-plus-circle.png')
497
- ACTION_EDIT = SpriteImage(32,272,'fa-pencil.png')
498
- ACTION_SELECT_FROM = SpriteImage(64,272,'fa-arrow-down.png')
499
- ACTION_SELECT_TO = SpriteImage(64,256,'fa-arrow-up.png')
500
- ACTION_COPY = SpriteImage(80,208,'clipboard-regular.png')
501
- ACTION_PASTE = SpriteImage(0,64,'paste-solid.png')
502
- ACTION_DUPLICATE = SpriteImage(48,208,'fa-files-o.png')
503
- ACTION_DELETE = SpriteImage(16,176,'fa-trash-o.png')
504
- ACTION_REFRESH = SpriteImage(32,144, 'fa-refresh.png')
505
- ACTION_RENAME = SpriteImage(0,48,'rename.png')
506
- ACTION_BROWSE = SpriteImage(32,304,'fa-folder-open.png')
507
- ACTION_DB = SpriteImage(48,288,'fa-database.png')
508
- ACTION_STOP = SpriteImage(16,256,'fa-stop.png')
509
- ACTION_CONTINUE = SpriteImage(32,256,'fa-play-circle-o.png')
510
- ACTION_STOP_WORKFLOW = SpriteImage(16,240,'fa-stop-workflow.png')
511
- ACTION_RESULTS = SpriteImage(48,240,'fa-eye.png')
512
- ACTION_SAVE = SpriteImage(32,112, 'fa-save.png')
481
+ RUNS_TREE = SpriteImage(16, 272, 'fa-sitemap.png')
482
+ ACTION_NEW = SpriteImage(80, 304, 'fa-plus-circle.png')
483
+ ACTION_EDIT = SpriteImage(32, 272, 'fa-pencil.png')
484
+ ACTION_SELECT_FROM = SpriteImage(64, 272, 'fa-arrow-down.png')
485
+ ACTION_SELECT_TO = SpriteImage(64, 256, 'fa-arrow-up.png')
486
+ ACTION_COPY = SpriteImage(80, 208, 'clipboard-regular.png')
487
+ ACTION_PASTE = SpriteImage(0, 64, 'paste-solid.png')
488
+ ACTION_DUPLICATE = SpriteImage(48, 208, 'fa-files-o.png')
489
+ ACTION_DELETE = SpriteImage(16, 176, 'fa-trash-o.png')
490
+ ACTION_REFRESH = SpriteImage(32, 144, 'fa-refresh.png')
491
+ ACTION_RENAME = SpriteImage(0, 48, 'rename.png')
492
+ ACTION_BROWSE = SpriteImage(32, 304, 'fa-folder-open.png')
493
+ ACTION_DB = SpriteImage(48, 288, 'fa-database.png')
494
+ ACTION_STOP = SpriteImage(16, 256, 'fa-stop.png')
495
+ ACTION_CONTINUE = SpriteImage(32, 256, 'fa-play-circle-o.png')
496
+ ACTION_STOP_WORKFLOW = SpriteImage(16, 240, 'fa-stop-workflow.png')
497
+ ACTION_RESULTS = SpriteImage(48, 240, 'fa-eye.png')
498
+ ACTION_SAVE = SpriteImage(32, 112, 'fa-save.png')
513
499
  ACTION_VISUALIZE = ACTION_RESULTS
514
- ACTION_WIZ = SpriteImage(32,288,'fa-magic.png')
515
- ACTION_HELP = SpriteImage(32,160,'fa-question-circle.png')
516
- ACTION_REFERENCES = SpriteImage(48,256,'link')
500
+ ACTION_WIZ = SpriteImage(32, 288, 'fa-magic.png')
501
+ ACTION_HELP = SpriteImage(32, 160, 'fa-question-circle.png')
502
+ ACTION_REFERENCES = SpriteImage(48, 256, 'link')
517
503
  ACTION_EXPORT = ACTION_REFERENCES
518
- ACTION_EXPORT_UPLOAD = SpriteImage(16,96, 'fa-upload.png')
519
- ACTION_SEARCH = SpriteImage(32,96, 'fa-search.png')
520
- SETTINGS = SpriteImage(48,304,'fa-cogs.png')
504
+ ACTION_EXPORT_UPLOAD = SpriteImage(16, 96, 'fa-upload.png')
505
+ ACTION_SEARCH = SpriteImage(32, 96, 'fa-search.png')
506
+ SETTINGS = SpriteImage(48, 304, 'fa-cogs.png')
521
507
  ACTION_EXECUTE = SETTINGS
522
- ACTION_IN = SpriteImage(16,304,'fa-sign-in.png')
523
- ACTION_OUT = SpriteImage(16,288,'fa-sign-out.png')
524
- ACTION_FIND_NEXT = SpriteImage(32,208,'fa-next.png')
525
- ACTION_FIND_PREVIOUS = SpriteImage(32,192,'fa-previous.png')
526
- ACTION_COLLAPSE = SpriteImage(32,240,'fa-minus-square.png')
527
- ACTION_EXPAND = SpriteImage(32,224,'fa-plus-square.png')
528
- ACTION_CIRCLE = SpriteImage(48,192,'circle.png')
508
+ ACTION_IN = SpriteImage(16, 304, 'fa-sign-in.png')
509
+ ACTION_OUT = SpriteImage(16, 288, 'fa-sign-out.png')
510
+ ACTION_FIND_NEXT = SpriteImage(32, 208, 'fa-next.png')
511
+ ACTION_FIND_PREVIOUS = SpriteImage(32, 192, 'fa-previous.png')
512
+ ACTION_COLLAPSE = SpriteImage(32, 240, 'fa-minus-square.png')
513
+ ACTION_EXPAND = SpriteImage(32, 224, 'fa-plus-square.png')
514
+ ACTION_CIRCLE = SpriteImage(48, 192, 'circle.png')
529
515
  ACTION_PICKING = SpriteImage(64, 192, 'picking.png')
530
516
  ACTION_STATS = SpriteImage(80, 192, 'stats.png')
531
517
  ACTION_ZOOM = SpriteImage(64, 176, 'zoom.png')
@@ -536,38 +522,38 @@ class Icon:
536
522
 
537
523
 
538
524
  # Host template
539
- BUTTON_SELECT = SpriteImage(64,224,'fa-check.png')
540
- BUTTON_CANCEL = SpriteImage(64,240,'fa-ban.png')
525
+ BUTTON_SELECT = SpriteImage(64, 224, 'fa-check.png')
526
+ BUTTON_CANCEL = SpriteImage(64, 240, 'fa-ban.png')
541
527
  ACTION_CLOSE = BUTTON_CANCEL
542
528
  BUTTON_CLOSE = ACTION_CLOSE
543
529
  BUTTON_SAVE = ACTION_SAVE
544
530
 
545
531
  ARROW_UP = ACTION_SELECT_TO
546
- TAGS = SpriteImage(16,224,'fa-tags.png')
547
- HOME = SpriteImage(0,304,'fa-home.png')
548
- LIGHTBULB = SpriteImage(32,80,'fa-lightbulb-o.png')
549
- ROCKET = SpriteImage(32,128, 'fa-rocket.png')
532
+ TAGS = SpriteImage(16, 224, 'fa-tags.png')
533
+ HOME = SpriteImage(0, 304, 'fa-home.png')
534
+ LIGHTBULB = SpriteImage(32, 80, 'fa-lightbulb-o.png')
535
+ ROCKET = SpriteImage(32, 128, 'fa-rocket.png')
550
536
 
551
537
  # File browser icons
552
538
  FOLDER_OPEN = ACTION_BROWSE
553
- DB = SpriteImage(0,144,'file_sqlite.png')
554
- TXT_FILE = SpriteImage(0,96,'file_text.png')
555
- FILE_VOL = SpriteImage(0,80,'file_vol.png')
556
- FILE_STACK = SpriteImage(0,112,'file_stack.png')
557
- FILE_STACK_LINK = SpriteImage(0,128, 'file_stack_link.png')
558
- PYTHON_FILE = SpriteImage(0,160,'file_python.png')
559
- FILE_METADATA = SpriteImage(0,176,'file_md.png')
560
- FILE_METADATA_LINK = SpriteImage(0,192, 'file_md_link.png')
561
- FILE_IMAGE = SpriteImage(0,208, 'file_image.png')
562
- FILE_IMAGE_LINK = SpriteImage(0,224, 'file_image_link.png')
563
- FILE = SpriteImage(0,240, 'file_generic.png')
564
- FILE_LINK = SpriteImage(0,256, 'file_generic_link.png')
565
- FOLDER = SpriteImage(0,272, 'file_folder.png')
566
- FOLDER_LINK = SpriteImage(0,288, 'file_folder_link.png')
567
-
568
- BROOM = SpriteImage(80,240,'broom-solid.png')
569
- BACKWARD = SpriteImage(80,288,'backward-solid.png')
570
- CODE_BRANCH = SpriteImage(64,304,'code-branch-solid.png')
539
+ DB = SpriteImage(0, 144, 'file_sqlite.png')
540
+ TXT_FILE = SpriteImage(0, 96, 'file_text.png')
541
+ FILE_VOL = SpriteImage(0, 80, 'file_vol.png')
542
+ FILE_STACK = SpriteImage(0, 112, 'file_stack.png')
543
+ FILE_STACK_LINK = SpriteImage(0, 128, 'file_stack_link.png')
544
+ PYTHON_FILE = SpriteImage(0, 160, 'file_python.png')
545
+ FILE_METADATA = SpriteImage(0, 176, 'file_md.png')
546
+ FILE_METADATA_LINK = SpriteImage(0, 192, 'file_md_link.png')
547
+ FILE_IMAGE = SpriteImage(0, 208, 'file_image.png')
548
+ FILE_IMAGE_LINK = SpriteImage(0, 224, 'file_image_link.png')
549
+ FILE = SpriteImage(0, 240, 'file_generic.png')
550
+ FILE_LINK = SpriteImage(0, 256, 'file_generic_link.png')
551
+ FOLDER = SpriteImage(0, 272, 'file_folder.png')
552
+ FOLDER_LINK = SpriteImage(0, 288, 'file_folder_link.png')
553
+
554
+ BROOM = SpriteImage(80, 240, 'broom-solid.png')
555
+ BACKWARD = SpriteImage(80, 288, 'backward-solid.png')
556
+ CODE_BRANCH = SpriteImage(64, 304, 'code-branch-solid.png')
571
557
 
572
558
  # Dialog icons
573
559
  ERROR = 'fa-times-circle_alert.png'
@@ -585,20 +571,20 @@ class Icon:
585
571
  CHIMERA = 'chimera.png'
586
572
 
587
573
  # PLUGIN MANAGER ICONS
588
- CHECKED = SpriteImage(64,208,'fa-checked.png')
589
- UNCHECKED = SpriteImage(16,160,'fa-unchecked.png')
590
- INSTALL = SpriteImage(32,64,'fa-install.png')
574
+ CHECKED = SpriteImage(64, 208, 'fa-checked.png')
575
+ UNCHECKED = SpriteImage(16, 160, 'fa-unchecked.png')
576
+ INSTALL = SpriteImage(32, 64, 'fa-install.png')
591
577
  UNINSTALL = ACTION_CLOSE
592
- TO_INSTALL = SpriteImage(32,256,'fa-to_install.png')
593
- INSTALLED = SpriteImage(16, 64,'fa-installed.png')
594
- PROCESSING = SpriteImage(32, 176, 'fa-processing.png',48,192)
595
- FAILURE = SpriteImage(48,224,'fa-failure.png')
578
+ TO_INSTALL = SpriteImage(32, 256, 'fa-to_install.png')
579
+ INSTALLED = SpriteImage(16, 64, 'fa-installed.png')
580
+ PROCESSING = SpriteImage(32, 176, 'fa-processing.png', 48, 192)
581
+ FAILURE = SpriteImage(48, 224, 'fa-failure.png')
596
582
  DELETE_OPERATION = ACTION_DELETE
597
- TO_UPDATE = SpriteImage(32,144,'fa-update.png')
583
+ TO_UPDATE = SpriteImage(32, 144, 'fa-update.png')
598
584
  WAITING = 'wait.gif'
599
- ACTION_UNDO = SpriteImage(16,144,'fa-undo.png')
585
+ ACTION_UNDO = SpriteImage(16, 144, 'fa-undo.png')
600
586
 
601
- PLUGIN_AUTHORS = SpriteImage(16,80,'users.png')
587
+ PLUGIN_AUTHORS = SpriteImage(16, 80, 'users.png')
602
588
  PLUGIN_DESCRIPTION = FILE_STACK
603
589
  PLUGIN_RELEASE_DATE = ACTION_EXPORT_UPLOAD
604
590
  PLUGIN_VERSION = FILE_VOL
pyworkflow/utils/utils.py CHANGED
@@ -22,6 +22,7 @@
22
22
  # *
23
23
  # **************************************************************************
24
24
  import logging
25
+
25
26
  logger = logging.getLogger(__name__)
26
27
 
27
28
  import contextlib
@@ -36,7 +37,7 @@ import sysconfig
36
37
  import bibtexparser
37
38
  import numpy as np
38
39
  import math
39
- from pyworkflow.constants import StrColors
40
+ from pyworkflow.constants import StrColors, TRUE_YES_ON_
40
41
  from pyworkflow import Config
41
42
 
42
43
 
@@ -705,7 +706,7 @@ def envVarOn(varName, env=None):
705
706
 
706
707
  def strToBoolean(string):
707
708
  """ Converts a string into a Boolean if the string is on of true, yes, on, 1. Case insensitive."""
708
- return string is not None and string.lower() in ['true', 'yes', 'on', '1']
709
+ return string is not None and string.lower() in TRUE_YES_ON_
709
710
 
710
711
  def strToDuration(durationStr):
711
712
  """ Converts a string representing an elapsed time to seconds
pyworkflow/viewer.py CHANGED
@@ -133,6 +133,22 @@ class Viewer(object):
133
133
  self._keyPressed = args.get('keyPressed', None)
134
134
  self._tkRoot = self.formWindow.root if self.formWindow else None
135
135
 
136
+ @classmethod
137
+ def can_handle_this(cls, classHierarchy, instance=None):
138
+ """ Returns none if it cannot handle the instance, otherwise returns which of the
139
+ classes of the hierarchy it targets (used for establishing priority"""
140
+
141
+ for t in cls._targets:
142
+ if t in classHierarchy:
143
+
144
+ if instance is not None and not cls.can_handle_this_instance(instance):
145
+ return None
146
+ else:
147
+ return t
148
+
149
+ @classmethod
150
+ def can_handle_this_instance(cls, instance):
151
+ return True
136
152
  def getKeyPressed(self):
137
153
  return self._keyPressed
138
154
 
@@ -222,6 +238,8 @@ class ProtocolViewer(Viewer, pwprot.Protocol):
222
238
  If should provide a mapping between form params and the corresponding
223
239
  functions that will return the corresponding Views.
224
240
  """
241
+
242
+ _label ="Protocol viewer"
225
243
  def __init__(self, **kwargs):
226
244
  # Here we are going to intercept the original _defineParams function
227
245
  # and replace by an empty one, this is to postpone the definition of
@@ -241,7 +259,11 @@ class ProtocolViewer(Viewer, pwprot.Protocol):
241
259
 
242
260
  def getWindow(self):
243
261
  return self.formWindow
244
-
262
+
263
+ @classmethod
264
+ def getName(cls):
265
+ return cls._label
266
+
245
267
  def getTkRoot(self):
246
268
  return self._tkRoot
247
269
 
@@ -1,9 +1,6 @@
1
1
  # Variable related to the online services (workflow stats and repository) that Scipion reports to or communicate.
2
2
  # These variables may change between Scipion versions but do not depend on the user or system
3
3
 
4
- # Web that gathers protocol usage
5
- SCIPION_STATS_SERVER = 'https://scipion.i2pc.es'
6
- SCIPION_STATS_WORKFLOW_APP = SCIPION_STATS_SERVER + '/report_protocols/api/workflow/workflow/'
7
4
 
8
5
  # Web that handles workflows
9
6
  WORKFLOW_REPOSITORY_SERVER = 'https://workflows.scipion.i2pc.es/'
@@ -34,9 +34,9 @@ from datetime import timedelta, datetime
34
34
  from urllib.parse import urlencode
35
35
  from urllib.request import build_opener, HTTPHandler
36
36
 
37
- import pyworkflow
38
37
  import pyworkflow.utils as pwutils
39
- from . import config
38
+ from pyworkflow import Config
39
+
40
40
 
41
41
 
42
42
  class ProjectWorkflowNotifier(object):
@@ -79,18 +79,32 @@ class ProjectWorkflowNotifier(object):
79
79
 
80
80
  return delta < timedelta(seconds=seconds)
81
81
 
82
- def _sendData(self, url, dataDict=None):
82
+ def _sendData(self, url, project_workflow):
83
83
  try:
84
84
  # then connect to webserver a send json
85
85
  # set debuglevel=0 for no messages
86
+
87
+ dataDict = {'project_uuid': self._getUuid(),
88
+ 'project_workflow': project_workflow}
89
+
86
90
  opener = build_opener(HTTPHandler(debuglevel=0))
87
91
  data = urlencode(dataDict).encode()
88
- content = opener.open(url, data=data).read()
92
+ opener.open(url, data=data).read()
93
+
94
+ # Store file time stamp with last time it was sent
89
95
  now = time.time()
90
96
  os.utime(self._getUuidFileName(), (now, now))
97
+
98
+ # Write what was sent in a file for _modifiedBefore to check file TS and avoid resending stats
99
+ dataFile = self._getDataFileName()
100
+ # create the folder of the file path if not exists
101
+ pwutils.makeFilePath(dataFile)
102
+ with open(dataFile, 'w') as f:
103
+ f.write(project_workflow)
104
+
91
105
  except Exception as e:
106
+ # Tolerate errors
92
107
  pass
93
- # print("Could not notify, maybe there is not internet connection.")
94
108
 
95
109
  def _dataModified(self, projectWorfklow):
96
110
  try:
@@ -106,12 +120,13 @@ class ProjectWorkflowNotifier(object):
106
120
 
107
121
  try:
108
122
  # check if environment exists otherwise abort
109
- if not pyworkflow.Config.SCIPION_NOTIFY:
123
+ if not Config.SCIPION_NOTIFY:
110
124
  return
111
125
 
112
126
  # if project specifies not to send stats
113
127
  if self._isProjectMuted():
114
128
  return
129
+
115
130
  # Check the seconds range of the notify, by default one day
116
131
  seconds = int(os.environ.get('SCIPION_NOTIFY_SECONDS', '86400'))
117
132
 
@@ -120,28 +135,11 @@ class ProjectWorkflowNotifier(object):
120
135
 
121
136
  # INFO: now we are only sending the protocols names in the project.
122
137
  # We could pass namesOnly=False to get the full workflow template
123
- projectWorfklow = self.project.getProtocolsJson(namesOnly=True)
124
-
125
- # if list with workflow has not been altered do not sent it
126
- if not self._dataModified(projectWorfklow):
127
- return
128
- else:
129
- # For compatibility with version 1.0 check
130
- # if Log directory exists. If it does not
131
- # create it
132
- # TODO: REMOVE this check in scipion 1.3
133
- dataFile = self._getDataFileName()
134
- # create the folder of the file path if not exists
135
- pwutils.makeFilePath(dataFile)
136
- with open(dataFile, 'w') as f:
137
- f.write(projectWorfklow)
138
- dataDict = {'project_uuid': self._getUuid(),
139
- 'project_workflow': projectWorfklow}
138
+ project_workflow = self.project.getProjectUsage().toJSON() # self.project.getProtocolsJson(namesOnly=True)
140
139
 
141
- urlName = os.environ.get('SCIPION_NOTIFY_URL',
142
- config.SCIPION_STATS_WORKFLOW_APP).strip()
140
+ urlName = Config.SCIPION_STATS_WORKFLOW_APP.strip()
143
141
  urlName += "addOrUpdateWorkflow/"
144
- t = threading.Thread(name="notifier", target=lambda: self._sendData(urlName, dataDict))
142
+ t = threading.Thread(name="notifier", target=lambda: self._sendData(urlName, project_workflow))
145
143
  t.start() # will execute function in a separate thread
146
144
  except Exception as e:
147
145
  print("Can't report usage: ", e)
@@ -152,11 +150,3 @@ class ProjectWorkflowNotifier(object):
152
150
  a test and therefore no statistics will be sent"""
153
151
  return os.path.basename(self.project.name).startswith("Test")
154
152
 
155
- def getEntryFromWebservice(self, uuid):
156
- if not pyworkflow.Config.SCIPION_NOTIFY:
157
- return
158
- urlName = os.environ.get('SCIPION_NOTIFY_URL').strip()
159
- # remove last directory
160
- urlName = os.path.split(urlName)[0]
161
- url = urlName + "/?project_uuid=" + uuid
162
- resultDict = self._sendData(url)
@@ -69,9 +69,7 @@ class ParallelSleepingProtocol(SleepingProtocol):
69
69
  class ConcurrencyProtocol(SleepingProtocol):
70
70
  """ Protocol to test concurrency access to sets"""
71
71
 
72
- def __init__(self, **kwargs):
73
- super().__init__(**kwargs)
74
- self.stepsExecutionMode = pwprot.STEPS_PARALLEL
72
+ stepsExecutionMode = pwprot.STEPS_PARALLEL
75
73
 
76
74
  def _defineParams(self, form):
77
75
  form.addParallelSection(threads=2, mpi=0)
@@ -98,6 +98,10 @@ class TestProtocolExecution(pwtests.BaseTest):
98
98
 
99
99
 
100
100
  currThread = threading.currentThread()
101
+ def needForGPU():
102
+ return True
103
+
104
+ currThread.needsGPU =needForGPU
101
105
  currThread.thId = 1
102
106
  self.assertEqual(stepExecutor.getGpuList(),[], "Gpu list should be empty")
103
107
 
@@ -1,22 +1,15 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: scipion-pyworkflow
3
- Version: 3.10.6
4
- Summary: Simple workflow platform used in scientific applications, initially developed within the Scipion framework for image processing in Electron Microscopy.
5
- Home-page: https://github.com/scipion-em/scipion-pyworkflow
6
- Author: J.M. De la Rosa Trevin, Roberto Marabini, Grigory Sharov, Josue Gomez Blanco, Pablo Conesa, Yunior Fonseca Reyna
7
- Author-email: delarosatrevin@scilifelab.se, roberto@cnb.csic.es, gsharov@mrc-lmb.cam.ac.uk, josue.gomez-blanco@mcgill.ca, pconesa@cnb.csic.es, fonsecareyna@cnb.csic.es
8
- Project-URL: Bug Reports, https://github.com/scipion-em/scipion-pyworkflow/issues
9
- Project-URL: Source, https://github.com/scipion-em/scipion-pyworkflow/
10
- Keywords: workflows science electron-microscopy cryo-em structural-biology image-processing scipion
11
- Classifier: Development Status :: 5 - Production/Stable
12
- Classifier: Intended Audience :: Science/Research
13
- Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
14
- Classifier: Programming Language :: Python :: 3.8
15
- Classifier: Programming Language :: Python :: 3.9
16
- Classifier: Programming Language :: Python :: 3.10
17
- Classifier: Programming Language :: Python :: 3.11
18
- Classifier: Programming Language :: Python :: 3.12
19
- Classifier: Topic :: Scientific/Engineering
3
+ Version: 3.11.1
4
+ Summary: Workflow platform used in scientific applications, initially developed within the Scipion framework for image processing in Electron Microscopy but generic by design to be applied to any domain.
5
+ Author-email: Pablo Conesa <pconesa@cnb.csic.es>, Yunior Fonseca <cfonseca@cnb.csic.es>, "J.M. De la Rosa Trevin" <josemiguel.delarosatrevin@stjude.org>, Roberto Marabini <roberto@cnb.csic.es>, Grigory Sharov <sharov.grigory@gmail.com>, Josue Gomez Blanco <josue.gomez-blanco@mcgill.ca>
6
+ License: GNU General Public License v3 (GPLv3)
7
+ Project-URL: Homepage, https://scipion.i2pc.es
8
+ Project-URL: Repository, https://github.com/scipion-em/scipion-pyworkflow
9
+ Project-URL: Issues, https://github.com/scipion-em/scipion-pyworkflow/issues
10
+ Keywords: scipion,electron-microscopy,cryo-em,structural-biology,generic-workflow-engine,image-processing,scipion-3.0
11
+ Requires-Python: >=3.8
12
+ Description-Content-Type: text/x-rst
20
13
  License-File: LICENSE.txt
21
14
  Requires-Dist: bibtexparser<=1.4.1
22
15
  Requires-Dist: psutil<=5.9.6
@@ -27,19 +20,12 @@ Requires-Dist: pillow==10.1.0; python_version >= "3.8"
27
20
  Requires-Dist: numpy==1.24.4; python_version == "3.8"
28
21
  Requires-Dist: numpy==1.26.1; python_version >= "3.9"
29
22
  Requires-Dist: requests==2.31.0; python_version >= "3.8"
30
- Requires-Dist: tkcolorpicker
23
+ Requires-Dist: tkcolorpicker2
31
24
  Requires-Dist: distro<=1.8
32
25
  Requires-Dist: importlib-metadata<=6.8.0
33
- Dynamic: author
34
- Dynamic: author-email
35
- Dynamic: classifier
36
- Dynamic: description
37
- Dynamic: home-page
38
- Dynamic: keywords
26
+ Requires-Dist: setuptools>=62.6
27
+ Requires-Dist: pyperclip==1.9.0
39
28
  Dynamic: license-file
40
- Dynamic: project-url
41
- Dynamic: requires-dist
42
- Dynamic: summary
43
29
 
44
30
  .. image:: https://img.shields.io/pypi/v/scipion-pyworkflow.svg
45
31
  :target: https://pypi.python.org/pypi/scipion-pyworkflow