Skip to content

Commit 6e33bdc

Browse files
committedMay 14, 2018
[pyqgis] move qgis.core tricks to their own python file in additions folder
this makes the code much easier to read
1 parent c985092 commit 6e33bdc

File tree

11 files changed

+488
-329
lines changed

11 files changed

+488
-329
lines changed
 

‎python/core/__init__.py

Lines changed: 11 additions & 329 deletions
Original file line numberDiff line numberDiff line change
@@ -16,350 +16,32 @@
1616
* *
1717
***************************************************************************
1818
"""
19-
from builtins import str
20-
from builtins import object
2119

2220
__author__ = 'Nathan Woodrow'
2321
__date__ = 'May 2014'
2422
__copyright__ = '(C) 2014, Nathan Woodrow'
2523
# This will get replaced with a git SHA1 when you do a git archive
2624
__revision__ = '$Format:%H$'
2725

28-
from qgis.PyQt.QtCore import QCoreApplication, NULL
2926

30-
import inspect
31-
import string
32-
import types
33-
import functools
3427
from qgis._core import *
3528

36-
37-
# Boolean evaluation of QgsGeometry
38-
39-
40-
def _geometryNonZero(self):
41-
return not self.isEmpty()
42-
43-
44-
def _isValid(self):
45-
return self.isValid()
46-
47-
29+
from .additions.readwritecontextentercategory import ReadWriteContextEnterCategory
30+
from .additions.projectdirtyblocker import ProjectDirtyBlocker
31+
from .additions.qgstaskwrapper import QgsTaskWrapper
32+
from .additions.qgsfunction import register_function, qgsfunction
33+
from .additions.edit import edit, QgsEditError
34+
from .additions.fromfunction import fromFunction
35+
from .additions.processing import processing_output_layer_repr, processing_source_repr
36+
from .additions.qgsgeometry import _geometryNonZero
37+
from .additions.qgsdefaultvalue import _isValid
38+
39+
# Injections into classes
4840
QgsGeometry.__nonzero__ = _geometryNonZero
4941
QgsGeometry.__bool__ = _geometryNonZero
50-
5142
QgsDefaultValue.__bool__ = _isValid
52-
53-
54-
def register_function(function, arg_count, group, usesgeometry=False,
55-
referenced_columns=[QgsFeatureRequest.ALL_ATTRIBUTES], **kwargs):
56-
"""
57-
Register a Python function to be used as a expression function.
58-
59-
Functions should take (values, feature, parent) as args:
60-
61-
Example:
62-
def myfunc(values, feature, parent):
63-
pass
64-
65-
They can also shortcut naming feature and parent args by using *args
66-
if they are not needed in the function.
67-
68-
Example:
69-
def myfunc(values, *args):
70-
pass
71-
72-
Functions should return a value compatible with QVariant
73-
74-
Eval errors can be raised using parent.setEvalErrorString("Error message")
75-
76-
:param function:
77-
:param arg_count:
78-
:param group:
79-
:param usesgeometry:
80-
:return:
81-
"""
82-
83-
class QgsPyExpressionFunction(QgsExpressionFunction):
84-
85-
def __init__(self, func, name, args, group, helptext='', usesGeometry=True,
86-
referencedColumns=QgsFeatureRequest.ALL_ATTRIBUTES, expandargs=False):
87-
QgsExpressionFunction.__init__(self, name, args, group, helptext)
88-
self.function = func
89-
self.expandargs = expandargs
90-
self.uses_geometry = usesGeometry
91-
self.referenced_columns = referencedColumns
92-
93-
def func(self, values, context, parent, node):
94-
feature = None
95-
if context:
96-
feature = context.feature()
97-
98-
try:
99-
if self.expandargs:
100-
values.append(feature)
101-
values.append(parent)
102-
if inspect.getargspec(self.function).args[-1] == 'context':
103-
values.append(context)
104-
return self.function(*values)
105-
else:
106-
if inspect.getargspec(self.function).args[-1] == 'context':
107-
self.function(values, feature, parent, context)
108-
return self.function(values, feature, parent)
109-
except Exception as ex:
110-
parent.setEvalErrorString(str(ex))
111-
return None
112-
113-
def usesGeometry(self, node):
114-
return self.uses_geometry
115-
116-
def referencedColumns(self, node):
117-
return self.referenced_columns
118-
119-
helptemplate = string.Template("""<h3>$name function</h3><br>$doc""")
120-
name = kwargs.get('name', function.__name__)
121-
helptext = kwargs.get('helpText') or function.__doc__ or ''
122-
helptext = helptext.strip()
123-
expandargs = False
124-
125-
if arg_count == "auto":
126-
# Work out the number of args we need.
127-
# Number of function args - 2. The last two args are always feature, parent.
128-
args = inspect.getargspec(function).args
129-
number = len(args)
130-
arg_count = number - 2
131-
if args[-1] == 'context':
132-
arg_count -= 1
133-
expandargs = True
134-
135-
register = kwargs.get('register', True)
136-
if register and QgsExpression.isFunctionName(name):
137-
if not QgsExpression.unregisterFunction(name):
138-
msgtitle = QCoreApplication.translate("UserExpressions", "User expressions")
139-
msg = QCoreApplication.translate("UserExpressions",
140-
"The user expression {0} already exists and could not be unregistered.").format(
141-
name)
142-
QgsMessageLog.logMessage(msg + "\n", msgtitle, Qgis.Warning)
143-
return None
144-
145-
function.__name__ = name
146-
helptext = helptemplate.safe_substitute(name=name, doc=helptext)
147-
f = QgsPyExpressionFunction(function, name, arg_count, group, helptext, usesgeometry, referenced_columns,
148-
expandargs)
149-
150-
# This doesn't really make any sense here but does when used from a decorator context
151-
# so it can stay.
152-
if register:
153-
QgsExpression.registerFunction(f)
154-
return f
155-
156-
157-
def qgsfunction(args='auto', group='custom', **kwargs):
158-
"""
159-
Decorator function used to define a user expression function.
160-
161-
Example:
162-
@qgsfunction(2, 'test'):
163-
def add(values, feature, parent):
164-
pass
165-
166-
Will create and register a function in QgsExpression called 'add' in the
167-
'test' group that takes two arguments.
168-
169-
or not using feature and parent:
170-
171-
Example:
172-
@qgsfunction(2, 'test'):
173-
def add(values, *args):
174-
pass
175-
"""
176-
177-
def wrapper(func):
178-
return register_function(func, args, group, **kwargs)
179-
180-
return wrapper
181-
182-
183-
class QgsEditError(Exception):
184-
185-
def __init__(self, value):
186-
self.value = value
187-
188-
def __str__(self):
189-
return repr(self.value)
190-
191-
192-
# Define a `with edit(layer)` statement
193-
194-
195-
class edit(object):
196-
197-
def __init__(self, layer):
198-
self.layer = layer
199-
200-
def __enter__(self):
201-
assert self.layer.startEditing()
202-
return self.layer
203-
204-
def __exit__(self, ex_type, ex_value, traceback):
205-
if ex_type is None:
206-
if not self.layer.commitChanges():
207-
raise QgsEditError(self.layer.commitErrors())
208-
return True
209-
else:
210-
self.layer.rollBack()
211-
return False
212-
213-
# Python class to mimic QgsReadWriteContextCategoryPopper C++ class
214-
215-
216-
class ReadWriteContextEnterCategory():
217-
"""
218-
Push a category to the stack
219-
220-
.. code-block:: python
221-
222-
context = QgsReadWriteContext()
223-
with QgsReadWriteContext.enterCategory(context, category, details):
224-
# do something
225-
226-
.. versionadded:: 3.2
227-
"""
228-
229-
def __init__(self, context, category_name, details=None):
230-
self.context = context
231-
self.category_name = category_name
232-
self.details = details
233-
self.popper = None
234-
235-
def __enter__(self):
236-
self.popper = self.context._enterCategory(self.category_name, self.details)
237-
return self.context
238-
239-
def __exit__(self, ex_type, ex_value, traceback):
240-
del self.popper
241-
return True
242-
243-
244-
# Inject the context manager into QgsReadWriteContext class as a member
24543
QgsReadWriteContext.enterCategory = ReadWriteContextEnterCategory
246-
247-
248-
# Python class to extend QgsProjectDirtyBlocker C++ class
249-
250-
251-
class ProjectDirtyBlocker():
252-
"""
253-
Context manager used to block project setDirty calls.
254-
255-
.. code-block:: python
256-
257-
project = QgsProject.instance()
258-
with QgsProject.blockDirtying(project):
259-
# do something
260-
261-
.. versionadded:: 3.2
262-
"""
263-
264-
def __init__(self, project):
265-
self.project = project
266-
self.blocker = None
267-
268-
def __enter__(self):
269-
self.blocker = QgsProjectDirtyBlocker(self.project)
270-
return self.project
271-
272-
def __exit__(self, ex_type, ex_value, traceback):
273-
del self.blocker
274-
return True
275-
276-
277-
# Inject the context manager into QgsProject class as a member
27844
QgsProject.blockDirtying = ProjectDirtyBlocker
279-
280-
281-
class QgsTaskWrapper(QgsTask):
282-
283-
def __init__(self, description, flags, function, on_finished, *args, **kwargs):
284-
QgsTask.__init__(self, description, flags)
285-
self.args = args
286-
self.kwargs = kwargs
287-
self.function = function
288-
self.on_finished = on_finished
289-
self.returned_values = None
290-
self.exception = None
291-
292-
def run(self):
293-
try:
294-
self.returned_values = self.function(self, *self.args, **self.kwargs)
295-
except Exception as ex:
296-
# report error
297-
self.exception = ex
298-
return False
299-
300-
return True
301-
302-
def finished(self, result):
303-
if not self.on_finished:
304-
return
305-
306-
if not result and self.exception is None:
307-
self.exception = Exception('Task canceled')
308-
309-
try:
310-
if self.returned_values:
311-
self.on_finished(self.exception, self.returned_values)
312-
else:
313-
self.on_finished(self.exception)
314-
except Exception as ex:
315-
self.exception = ex
316-
317-
318-
@staticmethod
319-
def fromFunction(description, function, *args, on_finished=None, flags=QgsTask.AllFlags, **kwargs):
320-
"""
321-
Creates a new QgsTask task from a python function.
322-
323-
Example:
324-
325-
def calculate(task):
326-
# pretend this is some complex maths and stuff we want
327-
# to run in the background
328-
return 5*6
329-
330-
def calculation_finished(exception, value=None):
331-
if not exception:
332-
iface.messageBar().pushMessage(
333-
'the magic number is {}'.format(value))
334-
else:
335-
iface.messageBar().pushMessage(
336-
str(exception))
337-
338-
task = QgsTask.fromFunction('my task', calculate,
339-
on_finished=calculation_finished)
340-
QgsApplication.taskManager().addTask(task)
341-
342-
"""
343-
344-
assert function
345-
return QgsTaskWrapper(description, flags, function, on_finished, *args, **kwargs)
346-
347-
34845
QgsTask.fromFunction = fromFunction
349-
350-
351-
# add some __repr__ methods to processing classes
352-
def processing_source_repr(self):
353-
return "<QgsProcessingFeatureSourceDefinition {{'source':{}, 'selectedFeaturesOnly': {}}}>".format(
354-
self.source.staticValue(), self.selectedFeaturesOnly)
355-
356-
35746
QgsProcessingFeatureSourceDefinition.__repr__ = processing_source_repr
358-
359-
360-
def processing_output_layer_repr(self):
361-
return "<QgsProcessingOutputLayerDefinition {{'sink':{}, 'createOptions': {}}}>".format(self.sink.staticValue(),
362-
self.createOptions)
363-
364-
36547
QgsProcessingOutputLayerDefinition.__repr__ = processing_output_layer_repr

‎python/core/additions/__init__.py

Whitespace-only changes.

‎python/core/additions/edit.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# -*- coding: utf-8 -*-
2+
3+
"""
4+
***************************************************************************
5+
edit.py
6+
---------------------
7+
Date : May 2018
8+
Copyright : (C) 2018 by Denis Rouzaud
9+
Email : denis@opengis.ch
10+
***************************************************************************
11+
* *
12+
* This program is free software; you can redistribute it and/or modify *
13+
* it under the terms of the GNU General Public License as published by *
14+
* the Free Software Foundation; either version 2 of the License, or *
15+
* (at your option) any later version. *
16+
* *
17+
***************************************************************************
18+
"""
19+
20+
from builtins import object
21+
22+
23+
class QgsEditError(Exception):
24+
25+
def __init__(self, value):
26+
self.value = value
27+
28+
def __str__(self):
29+
return repr(self.value)
30+
31+
32+
class edit(object):
33+
34+
def __init__(self, layer):
35+
self.layer = layer
36+
37+
def __enter__(self):
38+
assert self.layer.startEditing()
39+
return self.layer
40+
41+
def __exit__(self, ex_type, ex_value, traceback):
42+
if ex_type is None:
43+
if not self.layer.commitChanges():
44+
raise QgsEditError(self.layer.commitErrors())
45+
return True
46+
else:
47+
self.layer.rollBack()
48+
return False

‎python/core/additions/fromfunction.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# -*- coding: utf-8 -*-
2+
3+
"""
4+
***************************************************************************
5+
fromfunction.py
6+
---------------------
7+
Date : May 2018
8+
Copyright : (C) 2018 by Denis Rouzaud
9+
Email : denis@opengis.ch
10+
***************************************************************************
11+
* *
12+
* This program is free software; you can redistribute it and/or modify *
13+
* it under the terms of the GNU General Public License as published by *
14+
* the Free Software Foundation; either version 2 of the License, or *
15+
* (at your option) any later version. *
16+
* *
17+
***************************************************************************
18+
"""
19+
20+
from .qgstaskwrapper import QgsTaskWrapper
21+
from qgis._core import QgsTask
22+
23+
24+
@staticmethod
25+
def fromFunction(description, function, *args, on_finished=None, flags=QgsTask.AllFlags, **kwargs):
26+
"""
27+
Creates a new QgsTask task from a python function.
28+
29+
Example:
30+
31+
def calculate(task):
32+
# pretend this is some complex maths and stuff we want
33+
# to run in the background
34+
return 5*6
35+
36+
def calculation_finished(exception, value=None):
37+
if not exception:
38+
iface.messageBar().pushMessage(
39+
'the magic number is {}'.format(value))
40+
else:
41+
iface.messageBar().pushMessage(
42+
str(exception))
43+
44+
task = QgsTask.fromFunction('my task', calculate,
45+
on_finished=calculation_finished)
46+
QgsApplication.taskManager().addTask(task)
47+
48+
"""
49+
50+
assert function
51+
return QgsTaskWrapper(description, flags, function, on_finished, *args, **kwargs)

‎python/core/additions/processing.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# -*- coding: utf-8 -*-
2+
3+
"""
4+
***************************************************************************
5+
processing.py
6+
---------------------
7+
Date : May 2018
8+
Copyright : (C) 2018 by Denis Rouzaud
9+
Email : denis@opengis.ch
10+
***************************************************************************
11+
* *
12+
* This program is free software; you can redistribute it and/or modify *
13+
* it under the terms of the GNU General Public License as published by *
14+
* the Free Software Foundation; either version 2 of the License, or *
15+
* (at your option) any later version. *
16+
* *
17+
***************************************************************************
18+
"""
19+
20+
21+
# add some __repr__ methods to processing classes
22+
def processing_source_repr(self):
23+
return "<QgsProcessingFeatureSourceDefinition {{'source':{}, 'selectedFeaturesOnly': {}}}>".format(
24+
self.source.staticValue(), self.selectedFeaturesOnly)
25+
26+
27+
def processing_output_layer_repr(self):
28+
return "<QgsProcessingOutputLayerDefinition {{'sink':{}, 'createOptions': {}}}>".format(self.sink.staticValue(),
29+
self.createOptions)
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# -*- coding: utf-8 -*-
2+
3+
"""
4+
***************************************************************************
5+
projectdirtyblocker.py
6+
---------------------
7+
Date : May 2018
8+
Copyright : (C) 2018 by Denis Rouzaud
9+
Email : denis@opengis.ch
10+
***************************************************************************
11+
* *
12+
* This program is free software; you can redistribute it and/or modify *
13+
* it under the terms of the GNU General Public License as published by *
14+
* the Free Software Foundation; either version 2 of the License, or *
15+
* (at your option) any later version. *
16+
* *
17+
***************************************************************************
18+
"""
19+
20+
21+
from qgis._core import QgsProjectDirtyBlocker
22+
23+
24+
class ProjectDirtyBlocker():
25+
"""
26+
Context manager used to block project setDirty calls.
27+
28+
.. code-block:: python
29+
30+
project = QgsProject.instance()
31+
with QgsProject.blockDirtying(project):
32+
# do something
33+
34+
.. versionadded:: 3.2
35+
"""
36+
37+
def __init__(self, project):
38+
self.project = project
39+
self.blocker = None
40+
41+
def __enter__(self):
42+
self.blocker = QgsProjectDirtyBlocker(self.project)
43+
return self.project
44+
45+
def __exit__(self, ex_type, ex_value, traceback):
46+
del self.blocker
47+
return True
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# -*- coding: utf-8 -*-
2+
3+
"""
4+
***************************************************************************
5+
qgsdefaultvalue.py
6+
---------------------
7+
Date : May 2018
8+
Copyright : (C) 2018 by Denis Rouzaud
9+
Email : denis@opengis.ch
10+
***************************************************************************
11+
* *
12+
* This program is free software; you can redistribute it and/or modify *
13+
* it under the terms of the GNU General Public License as published by *
14+
* the Free Software Foundation; either version 2 of the License, or *
15+
* (at your option) any later version. *
16+
* *
17+
***************************************************************************
18+
"""
19+
20+
21+
def _isValid(self):
22+
return self.isValid()

‎python/core/additions/qgsfunction.py

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
# -*- coding: utf-8 -*-
2+
3+
"""
4+
***************************************************************************
5+
qgsfunction.py
6+
---------------------
7+
Date : May 2018
8+
Copyright : (C) 2018 by Denis Rouzaud
9+
Email : denis@opengis.ch
10+
***************************************************************************
11+
* *
12+
* This program is free software; you can redistribute it and/or modify *
13+
* it under the terms of the GNU General Public License as published by *
14+
* the Free Software Foundation; either version 2 of the License, or *
15+
* (at your option) any later version. *
16+
* *
17+
***************************************************************************
18+
"""
19+
20+
21+
import inspect
22+
import string
23+
from builtins import str
24+
from qgis.PyQt.QtCore import QCoreApplication
25+
from qgis._core import QgsExpressionFunction, QgsExpression, QgsMessageLog, QgsFeatureRequest
26+
27+
28+
def register_function(function, arg_count, group, usesgeometry=False,
29+
referenced_columns=[QgsFeatureRequest.ALL_ATTRIBUTES], **kwargs):
30+
"""
31+
Register a Python function to be used as a expression function.
32+
33+
Functions should take (values, feature, parent) as args:
34+
35+
Example:
36+
def myfunc(values, feature, parent):
37+
pass
38+
39+
They can also shortcut naming feature and parent args by using *args
40+
if they are not needed in the function.
41+
42+
Example:
43+
def myfunc(values, *args):
44+
pass
45+
46+
Functions should return a value compatible with QVariant
47+
48+
Eval errors can be raised using parent.setEvalErrorString("Error message")
49+
50+
:param function:
51+
:param arg_count:
52+
:param group:
53+
:param usesgeometry:
54+
:return:
55+
"""
56+
57+
class QgsPyExpressionFunction(QgsExpressionFunction):
58+
59+
def __init__(self, func, name, args, group, helptext='', usesGeometry=True,
60+
referencedColumns=QgsFeatureRequest.ALL_ATTRIBUTES, expandargs=False):
61+
QgsExpressionFunction.__init__(self, name, args, group, helptext)
62+
self.function = func
63+
self.expandargs = expandargs
64+
self.uses_geometry = usesGeometry
65+
self.referenced_columns = referencedColumns
66+
67+
def func(self, values, context, parent, node):
68+
feature = None
69+
if context:
70+
feature = context.feature()
71+
72+
try:
73+
if self.expandargs:
74+
values.append(feature)
75+
values.append(parent)
76+
if inspect.getargspec(self.function).args[-1] == 'context':
77+
values.append(context)
78+
return self.function(*values)
79+
else:
80+
if inspect.getargspec(self.function).args[-1] == 'context':
81+
self.function(values, feature, parent, context)
82+
return self.function(values, feature, parent)
83+
except Exception as ex:
84+
parent.setEvalErrorString(str(ex))
85+
return None
86+
87+
def usesGeometry(self, node):
88+
return self.uses_geometry
89+
90+
def referencedColumns(self, node):
91+
return self.referenced_columns
92+
93+
helptemplate = string.Template("""<h3>$name function</h3><br>$doc""")
94+
name = kwargs.get('name', function.__name__)
95+
helptext = kwargs.get('helpText') or function.__doc__ or ''
96+
helptext = helptext.strip()
97+
expandargs = False
98+
99+
if arg_count == "auto":
100+
# Work out the number of args we need.
101+
# Number of function args - 2. The last two args are always feature, parent.
102+
args = inspect.getargspec(function).args
103+
number = len(args)
104+
arg_count = number - 2
105+
if args[-1] == 'context':
106+
arg_count -= 1
107+
expandargs = True
108+
109+
register = kwargs.get('register', True)
110+
if register and QgsExpression.isFunctionName(name):
111+
if not QgsExpression.unregisterFunction(name):
112+
msgtitle = QCoreApplication.translate("UserExpressions", "User expressions")
113+
msg = QCoreApplication.translate("UserExpressions",
114+
"The user expression {0} already exists and could not be unregistered.").format(
115+
name)
116+
QgsMessageLog.logMessage(msg + "\n", msgtitle, Qgis.Warning)
117+
return None
118+
119+
function.__name__ = name
120+
helptext = helptemplate.safe_substitute(name=name, doc=helptext)
121+
f = QgsPyExpressionFunction(function, name, arg_count, group, helptext, usesgeometry, referenced_columns,
122+
expandargs)
123+
124+
# This doesn't really make any sense here but does when used from a decorator context
125+
# so it can stay.
126+
if register:
127+
QgsExpression.registerFunction(f)
128+
return f
129+
130+
131+
def qgsfunction(args='auto', group='custom', **kwargs):
132+
"""
133+
Decorator function used to define a user expression function.
134+
135+
Example:
136+
@qgsfunction(2, 'test'):
137+
def add(values, feature, parent):
138+
pass
139+
140+
Will create and register a function in QgsExpression called 'add' in the
141+
'test' group that takes two arguments.
142+
143+
or not using feature and parent:
144+
145+
Example:
146+
@qgsfunction(2, 'test'):
147+
def add(values, *args):
148+
pass
149+
"""
150+
151+
def wrapper(func):
152+
return register_function(func, args, group, **kwargs)
153+
154+
return wrapper

‎python/core/additions/qgsgeometry.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# -*- coding: utf-8 -*-
2+
3+
"""
4+
***************************************************************************
5+
qgsgeometry.py
6+
---------------------
7+
Date : May 2018
8+
Copyright : (C) 2018 by Denis Rouzaud
9+
Email : denis@opengis.ch
10+
***************************************************************************
11+
* *
12+
* This program is free software; you can redistribute it and/or modify *
13+
* it under the terms of the GNU General Public License as published by *
14+
* the Free Software Foundation; either version 2 of the License, or *
15+
* (at your option) any later version. *
16+
* *
17+
***************************************************************************
18+
"""
19+
20+
21+
def _geometryNonZero(self):
22+
return not self.isEmpty()
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# -*- coding: utf-8 -*-
2+
3+
"""
4+
***************************************************************************
5+
qgstaskwrapper.py
6+
---------------------
7+
Date : May 2018
8+
Copyright : (C) 2018 by Denis Rouzaud
9+
Email : denis@opengis.ch
10+
***************************************************************************
11+
* *
12+
* This program is free software; you can redistribute it and/or modify *
13+
* it under the terms of the GNU General Public License as published by *
14+
* the Free Software Foundation; either version 2 of the License, or *
15+
* (at your option) any later version. *
16+
* *
17+
***************************************************************************
18+
"""
19+
20+
21+
from qgis._core import QgsTask
22+
23+
24+
class QgsTaskWrapper(QgsTask):
25+
26+
def __init__(self, description, flags, function, on_finished, *args, **kwargs):
27+
QgsTask.__init__(self, description, flags)
28+
self.args = args
29+
self.kwargs = kwargs
30+
self.function = function
31+
self.on_finished = on_finished
32+
self.returned_values = None
33+
self.exception = None
34+
35+
def run(self):
36+
try:
37+
self.returned_values = self.function(self, *self.args, **self.kwargs)
38+
except Exception as ex:
39+
# report error
40+
self.exception = ex
41+
return False
42+
43+
return True
44+
45+
def finished(self, result):
46+
if not self.on_finished:
47+
return
48+
49+
if not result and self.exception is None:
50+
self.exception = Exception('Task canceled')
51+
52+
try:
53+
if self.returned_values:
54+
self.on_finished(self.exception, self.returned_values)
55+
else:
56+
self.on_finished(self.exception)
57+
except Exception as ex:
58+
self.exception = ex
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# -*- coding: utf-8 -*-
2+
3+
"""
4+
***************************************************************************
5+
readwritecontextentercategory.py
6+
---------------------
7+
Date : May 2018
8+
Copyright : (C) 2018 by Denis Rouzaud
9+
Email : denis@opengis.ch
10+
***************************************************************************
11+
* *
12+
* This program is free software; you can redistribute it and/or modify *
13+
* it under the terms of the GNU General Public License as published by *
14+
* the Free Software Foundation; either version 2 of the License, or *
15+
* (at your option) any later version. *
16+
* *
17+
***************************************************************************
18+
"""
19+
20+
21+
class ReadWriteContextEnterCategory():
22+
"""
23+
Push a category to the stack
24+
25+
.. code-block:: python
26+
27+
context = QgsReadWriteContext()
28+
with QgsReadWriteContext.enterCategory(context, category, details):
29+
# do something
30+
31+
.. versionadded:: 3.2
32+
"""
33+
34+
def __init__(self, context, category_name, details=None):
35+
self.context = context
36+
self.category_name = category_name
37+
self.details = details
38+
self.popper = None
39+
40+
def __enter__(self):
41+
self.popper = self.context._enterCategory(self.category_name, self.details)
42+
return self.context
43+
44+
def __exit__(self, ex_type, ex_value, traceback):
45+
del self.popper
46+
return True

0 commit comments

Comments
 (0)
Please sign in to comment.