proxies+verify kwargs break HTTP/2 in httpx - python

Versions: httpx 0.23.3 and httpcore 0.16.3.
import httpx
s=httpx.Client(
http2=True, proxies='http://127.0.0.1:9000', verify=False
)
r=s.get('https://in.indeed.com')
print(r.http_version)
Commenting out proxies/verify gives HTTP/2. The proxy is regular mitmproxy.
I've found this: https://github.com/encode/httpx/issues/873, but it was allegedly fixed in 2020. I've briefly viewed the respective code in httpx, and see http2 is passed everywhere, so probably it's somewhere deeper.

Well, I don't know what would be the proper way, but I've changed the line to set alpn_protocols to ["h2"] in httpcore in TunnelHTTPConnection/handle_request() to force it unconditionally, and it now gives me HTTP/2.

Related

`undetected_chromedriver` silently fails

I'm using a pretty standard boilerplate undetected_chromedriver installation:
LOCAL_CHRPATH = '/opt/google/chrome/chromedriver'
driver = uc.Chrome(
driver_executable_path=LOCAL_CHRPATH, headless=True
)
However, driver.get(url) simply fails silently, exiting the program. I have looked through the documentation, and found no way to get diagnostics pre or post get. Any idea of what to do or where to check?
You can pretty much ignore the specifics about the path and so on; the real question here is to understand why it fails.
Update: if I set debug to True, I get the same error that's indicated in this SO question. However, don't see a workaround for that. As an indication, this was working correctly with Python 3.10, stopped working when downgrading to 3.9
LOCAL_CHRPATH = '/opt/google/chrome/chromedriver'
This is local variable, not environmental. To set envvar you could:
os.environ["LOCAL_CHRPATH"] = '/opt/google/chrome/chromedriver'
Or just don't use envvars, or set default value:
driver = uc.Chrome(
driver_executable_path=os.getenv('LOCAL_CHRPATH', LOCAL_CHRPATH),
headless=True
)

Python slimit minimizer unwanted warning output

from slimit import minify
if __name__ == "__main__":
print("start")
# Normally, I pass real JavaScript. For this issue, an empty string reproduces problem.
minify("", mangle=True)
print("exit")
This triggers the following console output.
start
WARNING: Couldn't write lextab module <module 'slimit.lextab' from '/Users/kurtostfeld/samba/wrapad/venv/lib/python2.7/site-packages/slimit/lextab.pyc'>. Won't overwrite existing lextab module
WARNING: yacc table file version is out of date
WARNING: Token 'IMPORT' defined, but not used
WARNING: Token 'BLOCK_COMMENT' defined, but not used
WARNING: Token 'ENUM' defined, but not used
WARNING: Token 'EXTENDS' defined, but not used
WARNING: Token 'LINE_COMMENT' defined, but not used
WARNING: Token 'LINE_TERMINATOR' defined, but not used
WARNING: Token 'CONST' defined, but not used
WARNING: Token 'EXPORT' defined, but not used
WARNING: Token 'CLASS' defined, but not used
WARNING: Token 'SUPER' defined, but not used
WARNING: There are 10 unused tokens
WARNING: Couldn't create <module 'slimit.yacctab' from '/Users/kurtostfeld/samba/wrapad/venv/lib/python2.7/site-packages/slimit/yacctab.pyc'>. Won't overwrite existing tabmodule
exit
These warnings are flooding my application console output. How can I use minify without generating warnings?
I'm using Python 2.7.12, and what is currently the latest library versions: slimit 0.8.1, ply 3.10.
According to this issue on Github, slimit depends of the ply package. After few tries, it seems that theses warnings appear since version 3.8 of ply. . You could update ply to 3.6 which is the last version that doesn't bring these messages :
pip uninstall ply -y && pip install ply==3.6
It solved my problem.
UPDATE
Install a sooner version of ply was really a bad work around since some of my tests were failing. Original slimit version seems not maintained well so I suggest to update to a newer version, metatoaster did a good job to improve it and fixed that problem of warning message. The solution for me was to uninstall slimit and then install it's version:
pip install git+https://github.com/metatoaster/slimit.git#egg=slimit
FINAL UPDATE In fact, slimit seems not maintened anymore and its successor is called calmjs, there is few differences but it is really more stable and don't shows these annoying warning message. See: https://github.com/calmjs/calmjs.parse
Switching versions did not change anything for me, I found another workaround: simply delete (or move, if you want to be cautious) the mentioned files (yourpython/site-packages/slimit/yacctab.py and yourpython/site-packages/slimit/lextab.py).
I believe the module will re-create these files and stop bothering you with warning messages.
Slimit uses ply under the hood, which uses logging from stdlib. AFAICS slimit does not allow you to pass the logging parameters that ply's lex and yacc expect.
While you therefor can't (directly) access ply's logging, you should be able to suppress those messages my raising the global logging level:
import logging
...
logging.disable(logging.CRITICAL)
minify("", mangle=True)
logging.disable(logging.NOTSET)
You can use this parser, too: https://github.com/PiotrDabkowski/pyjsparser
It works and is easy to use. It does not handle comments though.
(Neither does calmjs seems to handle comments fully: Its parse function has a parameter to indicate that you want the comments, but as of now, some comments seem to get lost.)
Here was the solution that I went with. I made a custom variant of two slimit functions that pass an extra errorlog=ply.yacc.NullLogger() call to the ply.yacc.yacc function.
class SlimitNoLoggingParser(Parser):
"""
This is a simple customized variant to slimit.parser.Parser.
The only difference is that this passes a errorlog=ply.yacc.NullLogger() to ply.yacc.yacc to suppress unwanted
stderr logging output.
"""
def __init__(self, lex_optimize=True, lextab=lextab,
yacc_optimize=True, yacctab=yacctab, yacc_debug=False):
self.lex_optimize = lex_optimize
self.lextab = lextab
self.yacc_optimize = yacc_optimize
self.yacctab = yacctab
self.yacc_debug = yacc_debug
self.lexer = Lexer()
self.lexer.build(optimize=lex_optimize, lextab=lextab)
self.tokens = self.lexer.tokens
self.parser = ply.yacc.yacc(
module=self, optimize=yacc_optimize,
errorlog=ply.yacc.NullLogger(),
debug=yacc_debug, tabmodule=yacctab, start='program')
# https://github.com/rspivak/slimit/issues/29
# lexer.auto_semi can cause a loop in a parser
# when a parser error happens on a token right after
# a newline.
# We keep record of the tokens that caused p_error
# and if the token has already been seen - we raise
# a SyntaxError exception to avoid looping over and
# over again.
self._error_tokens = {}
# This is a simply variant of slimit.minify that suppresses unwanted noisy stderr logging output.
def warning_free_minify(text, mangle=False, mangle_toplevel=False):
parser = SlimitNoLoggingParser(lex_optimize=False)
tree = parser.parse(text)
if mangle:
mangler.mangle(tree, toplevel=mangle_toplevel)
minified = ECMAMinifier().visit(tree)
return minified

How to pass filter specific configuration options in webassets

Using flask, flask-assets, webassets
I am trying to pass a filter specific configuration for a particular filter in webassets, but haven't been able to do so, so far.
Have read the documentation multiple times to no avail. Have also gone through the source code, but that hasn't helped either.
Specifics:
The filter I'm trying to use is cleancss
And the particular configuration I'm trying to pass is --skip-rebase
According to the link to cleancss docs above, I should be able to pass the --skip-rebase option in CLEANCSS_EXTRA_ARGS. But where do I put that?
What I've tried so far, passing as flask config variables:
CLEANCSS_EXTRA_ARGS = ['--skip-rebase'] # actually works, see answer!
CLEANCSS_EXTRA_ARGS = ['skip-rebase'] # doesn't work!
ASSETS_CLEANCSS_EXTRA_ARGS = ['--skip-rebase'] # doesn't work!
FLASK_ASSETS_CLEANCSS_EXTRA_ARGS = ['--skip-rebase'] # doesn't work!
ASSETS_CLEANCSS_EXTRA_ARGS = ['skip-rebase'] # doesn't work!
FLASK_ASSETS_CLEANCSS_EXTRA_ARGS = ['skip-rebase'] # doesn't work!
ps: I also tried modifying the source to check if cleancss parameters are being correctly passed to the command line, and it is, so the problem is only in specifying the option correctly in the app configuration.
On retrying with the first option in question:
CLEANCSS_EXTRA_ARGS = ['--skip-rebase']
It worked!
More info available in the flask assets repo issues.
In my hurry I must have tried with:
CLEANCSS_EXTRA_ARGS = ['skip-rebase']
which didn't work and hence the question.
This feature should be documented though. Will probably submit a pull request for doc improvement.
Also note that this requires version 0.11 (webassets) and above.

How to get the AWS SQS metrics with python

At the moment we use the package boto to get queue messages and then, do some processing. The relevant code is:
from boto.sqs.message import RawMessage
import boto.sqs
import boto.sns
import json
conn = boto.sqs.connect_to_region(
"us-west-1",
aws_access_key_id="XXXXXXX",
aws_secret_access_key="XXXXXXX")
q=conn.get_queue('queueName')
q.set_message_class(RawMessage)
res=q.get_messages(10,wait_time_seconds=1)
....
and the rest is just processing code (not important for the question). This code works perfectly.
I was wondering if there is a way to, from python, get the metrics of the queue, for example, NumberOfMessagesSent.
Based on this post get metrics and the CloudWatch website, I thought there might be something like
conn = boto.sqs.cloudwatch.connect_to_region()
from which I could do
conn.get_metric_statistics()
but it does not seem to be the case (unless I have missed something).
I have found this very nice piece of code. But I was wondering if there is something "better" (or a more concise alternative) within boto.sqs
You can get the following attributes if you call q.get_attributes()
ApproximateNumberOfMessages, ApproximateNumberOfMessagesNotVisible,
VisibilityTimeout, CreatedTimestamp, LastModifiedTimestamp, Policy
ReceiveMessageWaitTimeSeconds
For things like NumberOfMessagesSent you will need to query CloudWatch for the data SQS logs there. The code you linked looks like the proper way to query CloudWatch metrics using boto.
Thanks,
Also, in case anyone finds it useful, we found a similar way to the one in the code I linked, but perhaps a little bit more concise.
import boto
import datetime
conn = boto.connect_cloudwatch(aws_access_key_id="xxx",aws_secret_access_key="xxx")
conn.get_metric_statistics(
300,
datetime.datetime.utcnow() - datetime.timedelta(seconds=300),
datetime.datetime.utcnow(),
'ApproximateNumberOfMessagesVisible',
'AWS/SQS',
'Average',
dimensions={'QueueName':['Myqueuename']}
)

Using mx:RemoteObject with web2py's #service.amfrpc decorator

I am using web2py (v1.63) and Flex 3. web2py v1.61 introduced the #service decorators, which allow you to tag a controller function with #service.amfrpc. You can then call that function remotely using http://..../app/default/call/amfrpc/[function]. See http://www.web2py.com/examples/default/tools#services. Does anybody have an example of how you would set up a Flex 3 to call a function like this? Here is what I have tried so far:
<mx:RemoteObject id="myRemote" destination="amfrpc" source="amfrpc"
endpoint="http://{mysite}/{myapp}/default/call/amfrpc/">
<mx:method name="getContacts"
result="show_results(event)"
fault="on_fault(event)" />
</mx:RemoteObject>
In my scenario, what should be the value of the destination and source attributes? I have read a couple of articles on non-web2py implementations, such as http://corlan.org/2008/10/10/flex-and-php-remoting-with-amfphp/, but they use a .../gateway.php file instead of having a URI that maps directly to the function.
Alternatively, I have been able to use flash.net.NetConnection to successfully call my remote function, but most of the documentation I have found considers this to be the old, pre-Flex 3 way of doing AMF. See http://pyamf.org/wiki/HelloWorld/Flex. Here is the NetConnection code:
gateway = new NetConnection();
gateway.connect("http://{mysite}/{myapp}/default/call/amfrpc/");
resp = new Responder(show_results, on_fault);
gateway.call("getContacts", resp);
-Rob
I have not found a way to use a RemoteObject with the #service.amfrpc decorator. However, I can use the older ActionScript code using a NetConnection (similar to what I posted originally) and pair that with a #service.amfrpc function on the web2py side. This seems to work fine. The one thing that you would want to change in the NetConnection code I shared originally, is adding an event listener for connection status. You can add more listeners if you feel the need, but I found that NetStatusEvent was a must. This status will be fired if the server is not responding. You connection set up would look like:
gateway = new NetConnection();
gateway.addEventListener(NetStatusEvent.NET_STATUS, gateway_status);
gateway.connect("http://127.0.0.1:8000/robs_amf/default/call/amfrpc/");
resp = new Responder(show_results, on_fault);
gateway.call("getContacts", resp);
-Rob

Categories