Trying to avoid having RQ display a warning message (to console) about using the meta dictionary for arbitrary property usage. We are using it as is specified, and the warning continues to display.
The warning displayed is as follows:
/usr/local/lib/python2.7/site-packages/rq/job.py:381: SyntaxWarning: Getting custom properties from the job instance directly will be unsupported as of RQ 0.4. Please use the meta dict to store all custom variables. So instead of this:
job.foo
Use this:
job.meta['foo']
SyntaxWarning)
Basically, it is pretty annoying because it interferes with normal debugging activities.
Any ideas on how to disable this?
Use the built-in warnings module's simplefilter method. Requires use of a context manager. Code example copied wholesale from the linked section:
import warnings
def fxn():
warnings.warn("deprecated", DeprecationWarning)
with warnings.catch_warnings():
warnings.simplefilter("ignore")
fxn()
Further arguments to simplefilter allow you to filter just the warnings you're getting from the specific place in the code you know about-- probably a good idea so other, new warnings that arise later won't be obscured.
Related
As the title states, what I want to achieve is the following:
I have a python code base for which I want to rename all the functions from camelCasing to underscore_naming. In order to maintain backwards compatibility, I have renamed all the functions, but have created function aliases for all the old names. So far, so good.
Now what I want to do is add deprecation warnings to the function aliases, preferably in a fashion like this:
def do_something():
...
#deprecated(deprecated_in='2.0',
details='All functions have been adapted to fit the PEP8 standard. Please use "do_something" instead')
doSomething = do_something
So that if somebody uses the old API call, they will get a deprecation warning. I've taken a look at deprecation and Deprecated, but neither of them seem to work on aliases.
I realise that I can create a function definition for every deprecated name and decorate that, but that loses the elegance of the function alias, and makes for more mucky code. Does anybody have a good suggestion to achieve what I want?
I actually ended up going for a different solution, similar to what's suggested in Method and property aliases with custom docstring in Python.
I modified my code to
#alias('doSomething', deprecated=True)
def do_something():
...
and added a deprecation warning to the alias decorator.
According to the docs you can ignore warnings like this:
#pytest.mark.filterwarnings("ignore:api v1")
def test_foo():
which gives:
But there doesn't seem to be any documentation on this mini-language (is it even a minilanguage?)
How is the match done?
I'm asking this because the following test doesn't ignore the DeprecationWarning raised by importing boto3:
#pytest.mark.filterwarnings("ignore:DeprecationWarning")
def test_ignore_warnings():
import boto3
Pytest outputs:
============================================================================================================================== warnings summary ===============================================================================================================================
/home/rob/dev/time-series/.venv/lib/python3.7/site-packages/botocore/awsrequest.py:624
/home/rob/dev/time-series/.venv/lib/python3.7/site-packages/botocore/awsrequest.py:624: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working
class HeadersDict(collections.MutableMapping):
-- Docs: https://docs.pytest.org/en/latest/warnings.html
==================================================================================================================== 1 passed, 1 warnings in 0.36 seconds =====================================================================================================================
The filters work the same way as when you use -W argument with python command (see python --help). The format is described in the documentation of the warnings module. In short it's action:message:category:module:line where action is probably mandatory but the other parts can be omitted.
"ignore:api v1" would try to match the message by defining "a string containing a regular expression that the start of the warning message must match". Since you actually want to match category you can skip message. This means that you just seem to be missing one colon after ignore so this is the correct format:
#pytest.mark.filterwarnings("ignore::DeprecationWarning")
def test_ignore_warnings():
import boto3
However, you might apparently still get the warning if it happens during an import of a package outside of a test function. In this case you might need to specify the filter globally as a pytest's argument:
pytest -W "ignore::DeprecationWarning" ./tests/
...or add it to pytest.ini:
[pytest]
filterwarnings =
ignore::DeprecationWarning
If such a global exclusion is undesirable, you can try to limit it to a particular module:
ignore::DeprecationWarning:boto3
Testing
For testing purposes, you can use the following code:
import warnings
def something():
warnings.warn("Test", DeprecationWarning)
#pytest.mark.filterwarnings("ignore::DeprecationWarning")
def test_ignore_warnings():
something()
How to disable the filtering of the warnings?
I would like to output several times the same warning, but a filter in the library avoids to output more than once the same warning.
import warnings
for i in range(2):
warnings.warn("warning message")
output:
C:\Users\me\my_script.py:4: UserWarning: warning message
warnings.warn("warning message")
The documentation is here:
https://docs.python.org/2/library/warnings.html
Apparently I have to set "always" in the tuple at the entry of the filter, I don't know how to do so, and where to access this tuple.
You can update warning filters with the warnings.simplefilter() and warnings.filterwarnings() functions; from the module intro:
The determination whether to issue a warning message is controlled by the warning filter, which is a sequence of matching rules and actions. Rules can be added to the filter by calling filterwarnings() and reset to its default state by calling resetwarnings().
To make all warnings repeat beyond the first issue, use
warnings.simplefilter('always')
You can expand on this by adding more details to filter on. For example, your warnings.warn() calls do not specify a category, so the default then is to use warnings.UserWarning; you could add that to the filter:
warnings.simplefilter('always', warnings.UserWarning)
etc. You can use keyword arguments too if you only want to specify some of the filter arguments, such as append=True.
With python 2.7.15rc1, to disable all warnings, I used these two lines of code:
import warnings
warnings.simplefilter("ignore")
I hope it is useful
Python now supports type hinting, so... yay! It seems like a great method to avoid some of the more obscure runtime bugs.
Sadly, third-party library support remains an issue. Though partially solved by the typeshed project, which is also used by mypy, when trying to port some of my code to use type hints, I ran into issues due to missing stubs.
E.g.
# file:mypytest.py
import lxml.etree as et
tree = et.fromstring('<root><a>1</a><b>2</b><a>3</a></root>')
items = tree.xpath('/root/a')
print([i.text for i in items])
will work perfectly well, but mypy will produce the spurious error message
>>> mypy mypytest.py
mypytest.py:3: error: "_Element" has no attribute "xpath"
because the stub is currently incomplete.
For a larger project, downloading the stub from typeshed, adding the missing entries, and maybe even submitting the corresponding pull request is a no-brainer.
But is there some method to monkey-patch the missing information in quick-and-dirty scenarios?
Bad workaround
The best I was able to come up with was
items = tree.xpath('/root/a') # type: ignore
which silences the error, but also disables type-checking where the variable items is used afterwards. E.g. items[0] + 1 will not cause a warning anymore.
In order to preserve type-checking it is possible to use
items_tmp = tree.xpath('/root/a') # type: ignore
items = items_tmp # type: List[et._Element]
but this seems hackish; It also has to be repeated everywhere the .xpath method is used.
Update from 2017-09-12: Alternatively one can use the syntax
items_tmp : List[et._Element] = tree.xpath('/root/a') # type: ignore
Is there a way I can get rid of delays on double_click_input() actions?
What I'm trying to do is double click the edit box and then type keys here. Maybe both of these actions have some delay, so the whole process performing looks very slow.
Code:
myApp = Desktop(backend='uia').window(title_re='myTitle_re')
myApp.window(auto_id='myAutoId').window(title='myTitle').double_click_input()
myApp.descendants(title='myTitle', control_type='Edit')[1].type_keys('myKeys')
And an additional question: I tried to use double_click() here, but it always throws an exception:
AttributeError: WindowSpecification class has no 'double_click'
method.
Then I tried myApp.window(auto_id='myAutoId').window(title='myTitle').wrapper_object().double_click()
And got:
AttributeError: 'ListItemWrapper' object has no attribute
'double_click'
What should I change to get this work?
I'm using pywinauto 0.6.3.
Answering your first question, you can set some timings to null using global settings. For double_click_input:
from pywinauto.timings import Timings
Timings.after_clickinput_wait = 0.0
Timings.after_setcursorpos_wait = 0.0
For real user input (*_input methods) changing timings may cause modified sequence not to work. But you may experiment for your own risk. Sometimes it's better to use silent methods using window messages like WM_CLICK (for "win32" backend) or UIAutomation Patterns like Invoke Pattern (for "uia" backend).
double_click is not implemented for "uia" because it's unclear which UIAutomation Pattern should be interpreted as double click action. We have method .invoke() and ButtonWrapper.click = invoke alias. But for non-buttons InvokePattern may have different meaning. That's why we left it as .invoke().
P.S. Regarding legacy propery text... It can be obtained by .legacy_properties()[u'Value'] for your case (or other value from returned dict). There are methods set_window_text/set_edit_text using ValuePattern so the text can be set silently without any tricks.