Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve processing monkey patching #58404

Merged
merged 4 commits into from
Aug 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions python/plugins/processing/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,17 @@
# monkey patch Python specific Processing API into stable qgis.processing module
import qgis.processing

algorithmHelp.__doc__ = qgis.processing.algorithmHelp.__doc__
qgis.processing.algorithmHelp = algorithmHelp
run.__doc__ = qgis.processing.run.__doc__
qgis.processing.run = run
runAndLoadResults.__doc__ = qgis.processing.runAndLoadResults.__doc__
qgis.processing.runAndLoadResults = runAndLoadResults
createAlgorithmDialog.__doc__ = qgis.processing.createAlgorithmDialog.__doc__
qgis.processing.createAlgorithmDialog = createAlgorithmDialog
execAlgorithmDialog.__doc__ = qgis.processing.execAlgorithmDialog.__doc__
qgis.processing.execAlgorithmDialog = execAlgorithmDialog
createContext.__doc__ = qgis.processing.createContext.__doc__
qgis.processing.createContext = createContext


Expand Down
12 changes: 3 additions & 9 deletions python/plugins/processing/tools/dataobjects.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,16 +51,10 @@
TYPE_TABLE = 5


# changing this signature? make sure you update the signature in
# python/processing/__init__.py too!
# Docstring for this function is in python/processing/__init__.py
def createContext(feedback=None):
"""
Creates a default processing context

:param feedback: Optional existing QgsProcessingFeedback object, or None to use a default feedback object
:type feedback: Optional[QgsProcessingFeedback]

:returns: New QgsProcessingContext object
:rtype: QgsProcessingContext
"""
context = QgsProcessingContext()
context.setProject(QgsProject.instance())
context.setFeedback(feedback)
Expand Down
72 changes: 16 additions & 56 deletions python/plugins/processing/tools/general.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,10 @@
from qgis.utils import iface


def algorithmHelp(id):
"""
Prints algorithm parameters with their types. Also
provides information about parameters and outputs,
and their acceptable values.

:param id: An algorithm's ID
:type id: str
"""
# changing this signature? make sure you update the signature in
# python/processing/__init__.py too!
# Docstring for this function is in python/processing/__init__.py
def algorithmHelp(id: str) -> None:
alg = QgsApplication.processingRegistry().algorithmById(id)
if alg is not None:
print(f'{alg.displayName()} ({alg.id()})\n')
Expand Down Expand Up @@ -90,21 +85,10 @@ def algorithmHelp(id):
print(f'Algorithm "{id}" not found.')


# changing this signature? make sure you update the signature in
# python/processing/__init__.py too!
# Docstring for this function is in python/processing/__init__.py
def run(algOrName, parameters, onFinish=None, feedback=None, context=None, is_child_algorithm=False):
"""
Executes given algorithm and returns its outputs as dictionary object.

:param algOrName: Either an instance of an algorithm, or an algorithm's ID
:param parameters: Algorithm parameters dictionary
:param onFinish: optional function to run after the algorithm has completed
:param feedback: Processing feedback object
:param context: Processing context object
:param is_child_algorithm: Set to True if this algorithm is being run as part of a larger algorithm,
i.e. it is a sub-part of an algorithm which calls other Processing algorithms.

:returns algorithm results as a dictionary, or None if execution failed
:rtype: Union[dict, None]
"""
if onFinish or not is_child_algorithm:
return Processing.runAlgorithm(algOrName, parameters, onFinish, feedback, context)
else:
Expand All @@ -117,19 +101,10 @@ def post_process(_alg, _context, _feedback):
return Processing.runAlgorithm(algOrName, parameters, onFinish=post_process, feedback=feedback, context=context)


# changing this signature? make sure you update the signature in
# python/processing/__init__.py too!
# Docstring for this function is in python/processing/__init__.py
def runAndLoadResults(algOrName, parameters, feedback=None, context=None):
"""
Executes given algorithm and load its results into the current QGIS project
when possible.

:param algOrName: Either an instance of an algorithm, or an algorithm's ID
:param parameters: Algorithm parameters dictionary
:param feedback: Processing feedback object
:param context: Processing context object

:returns algorithm results as a dictionary, or None if execution failed
:rtype: Union[dict, None]
"""
if isinstance(algOrName, QgsProcessingAlgorithm):
alg = algOrName
else:
Expand All @@ -153,18 +128,10 @@ def runAndLoadResults(algOrName, parameters, feedback=None, context=None):
context=context)


# changing this signature? make sure you update the signature in
# python/processing/__init__.py too!
# Docstring for this function is in python/processing/__init__.py
def createAlgorithmDialog(algOrName, parameters={}):
"""
Creates and returns an algorithm dialog for the specified algorithm, prepopulated
with a given set of parameters. It is the caller's responsibility to execute
and delete this dialog.

:param algOrName: Either an instance of an algorithm, or an algorithm's ID
:param parameters: Initial algorithm parameters dictionary

:returns algorithm results as a dictionary, or None if execution failed
:rtype: Union[dict, None]
"""
if isinstance(algOrName, QgsProcessingAlgorithm):
alg = algOrName.create()
else:
Expand All @@ -183,17 +150,10 @@ def createAlgorithmDialog(algOrName, parameters={}):
return dlg


# changing this signature? make sure you update the signature in
# python/processing/__init__.py too!
# Docstring for this function is in python/processing/__init__.py
def execAlgorithmDialog(algOrName, parameters={}):
"""
Executes an algorithm dialog for the specified algorithm, prepopulated
with a given set of parameters.

:param algOrName: Either an instance of an algorithm, or an algorithm's ID
:param parameters: Initial algorithm parameters dictionary

:returns algorithm results as a dictionary, or None if execution failed
:rtype: Union[dict, None]
"""
dlg = createAlgorithmDialog(algOrName, parameters)
if dlg is None:
return {}
Expand Down
119 changes: 119 additions & 0 deletions python/processing/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,125 @@
__date__ = 'November 2018'
__copyright__ = '(C) 2018, Nathan Woodrow'

import typing as _typing

from qgis.core import QgsProcessingAlgorithm as _QgsProcessingAlgorithm
from qgis.core import QgsProcessingFeedback as _QgsProcessingFeedback
from qgis.core import QgsProcessingContext as _QgsProcessingContext

from .algfactory import ProcessingAlgFactory

alg = ProcessingAlgFactory()


# "Forward declare" functions which will be patched in when the Processing plugin loads:
nyalldawson marked this conversation as resolved.
Show resolved Hide resolved

def algorithmHelp(id: str) -> None:
"""
Prints algorithm parameters with their types. Also
provides information about parameters and outputs,
and their acceptable values.

:param id: An algorithm's ID, eg "native:buffer"

:raises: QgsNotSupportedException if the Processing plugin has not been loaded
"""
from qgis.core import QgsNotSupportedException
raise QgsNotSupportedException('Processing plugin has not been loaded')


def run(algOrName: _typing.Union[str, _QgsProcessingAlgorithm],
parameters: _typing.Dict[str, object],
onFinish: _typing.Optional[_typing.Callable] = None,
feedback: _typing.Optional[_QgsProcessingFeedback] = None,
context: _typing.Optional[_QgsProcessingContext] = None,
is_child_algorithm: bool = False) -> _typing.Union[_typing.Dict, None]:
"""
Executes given algorithm and returns its outputs as dictionary object.

:param algOrName: Either an instance of an algorithm, or an algorithm's ID
:param parameters: Algorithm parameters dictionary
:param onFinish: optional function to run after the algorithm has completed
:param feedback: Processing feedback object
:param context: Processing context object
:param is_child_algorithm: Set to True if this algorithm is being run as part of a larger algorithm,
i.e. it is a sub-part of an algorithm which calls other Processing algorithms.

:return: algorithm results as a dictionary, or None if execution failed

:raises: QgsNotSupportedException if the Processing plugin has not been loaded
"""
from qgis.core import QgsNotSupportedException
raise QgsNotSupportedException('Processing plugin has not been loaded')


def runAndLoadResults(algOrName: _typing.Union[str, _QgsProcessingAlgorithm],
parameters: _typing.Dict[str, object],
feedback: _typing.Optional[_QgsProcessingFeedback] = None,
context: _typing.Optional[_QgsProcessingContext] = None) -> _typing.Union[_typing.Dict, None]:
"""
Executes given algorithm and load its results into the current QGIS project
when possible.

:param algOrName: Either an instance of an algorithm, or an algorithm's ID
:param parameters: Algorithm parameters dictionary
:param feedback: Processing feedback object
:param context: Processing context object

:return: algorithm results as a dictionary, or None if execution failed
:rtype: Union[dict, None]

:raises: QgsNotSupportedException if the Processing plugin has not been loaded
"""
from qgis.core import QgsNotSupportedException
raise QgsNotSupportedException('Processing plugin has not been loaded')


def createAlgorithmDialog(algOrName: _typing.Union[str, _QgsProcessingAlgorithm],
parameters: _typing.Dict[str, object] = {}) -> _typing.Union[str, _QgsProcessingAlgorithm]:
"""
Creates and returns an algorithm dialog for the specified algorithm, prepopulated
with a given set of parameters. It is the caller's responsibility to execute
and delete this dialog.

:param algOrName: Either an instance of an algorithm, or an algorithm's ID
:param parameters: Initial algorithm parameters dictionary

:return: algorithm results as a dictionary, or None if execution failed

:raises: QgsNotSupportedException if the Processing plugin has not been loaded
"""
from qgis.core import QgsNotSupportedException
raise QgsNotSupportedException('Processing plugin has not been loaded')


def execAlgorithmDialog(algOrName: _typing.Union[str, _QgsProcessingAlgorithm],
parameters: _typing.Dict[str, object] = {}) -> _typing.Union[_typing.Dict, None]:
"""
Executes an algorithm dialog for the specified algorithm, prepopulated
with a given set of parameters.

:param algOrName: Either an instance of an algorithm, or an algorithm's ID
:param parameters: Initial algorithm parameters dictionary

:return: algorithm results as a dictionary, or None if execution failed

:raises: QgsNotSupportedException if the Processing plugin has not been loaded
"""
from qgis.core import QgsNotSupportedException
raise QgsNotSupportedException('Processing plugin has not been loaded')


def createContext(feedback: _typing.Optional[_QgsProcessingFeedback] = None) -> _QgsProcessingContext:
"""
Creates a default processing context

:param feedback: Optional existing QgsProcessingFeedback object, or None to use a default feedback object
:type feedback: Optional[QgsProcessingFeedback]

:returns: New QgsProcessingContext object

:raises: QgsNotSupportedException if the Processing plugin has not been loaded
"""
from qgis.core import QgsNotSupportedException
raise QgsNotSupportedException('Processing plugin has not been loaded')
Loading