Currently I'm trying to fill all fields from a form using Python + uiautomator
My Code:
d = UIDevice(adb.deviceList[0].device)
last_item_exists = d(text='Memo').exists
while not last_item_exists:
print "Searching for fields on screen"
fields = d(className = 'android.widget.EditText', focusable = True)
for field in fields:
if not (field.text == '0' or field.text == '50'): #Skip fields with 0 or 50
print "Writing on the field"
field.click()
d.press(0x0000001d, 0x00001000)
d.press('del')
field.set_text('50')
else:
print "Skipping field"
print "Searching for Memo field"
last_item_exists = d(text='Memo').exists
print "Scrolling down"
d(scrollable=True).fling()
d(text='Confirm').click()
The Problem:
Depending on device resolution, this error may occur:
uiautomator.JsonRPCError: JsonRPC Error code: -32002, Message: com.android.uiautomator.core.UiObjectNotFoundException: UiSelector[CLASS=android.widget.EditText, INSTANCE=9, FOCUSABLE=true, RESOURCE_ID=com.salab.ABRT:id/task_info_item_count]
This is happening, because when I click on the last visible field field, the screen sometimes scrolls down a bit and the top field is not visible anymore.
Is there a workaround for this kind of problem, or I must change my logic(Can't think about anything right now...) ?
UiAutomator only sees what is visible on the screen at each moment. So if you scroll down (or the app does) then it can't interact with it.
You either change your logic or you swipe the screen up and down verifying if everything is filled and, if not, fill it.
Related
Our team has been using the Docusign Python API for about a year now and we've noticed this issue pretty consistently, then disappear for a few weeks, and now it's back again. Every time we generate a new template with Text tabs anchored somewhere on the document, the Tabs get duplicated into the upper-left corner of the document. The resulting document has a bunch of overlapping text fields in the corner of the first page, which looks very unprofessional and messy.
Here's what the template looks like. The two fields stacked on top of each other are hard to see since they've been shrunk down to the minimum size, but if I click on them I can see that their tab labels match the two fields on the page (broker_name and sign_date).
Then during the signing ceremony for an envelope built from this template, the empty fields get populated with data, and show up in the corner.
We generate the Tabs object with the following code:
# Returns a Tabs object with name and date tabs. For envelopes that only contain those two fields.
def generate_name_date_tabs(name, date):
name = Text(document_id = '1', page_number = '1', recipient_id = '1', value=name, tab_label = 'eh_broker_name')
date = Text(document_id = '1', page_number = '1', recipient_id = '1', value=date, tab_label = 'eh_sign_date')
return Tabs(text_tabs=[name, date])
And we generate the template and envelope here:
def create_application_envelope(destination_email, base64_file_content, signer_name="PlanProvide", signer_tabs=None, is_embedded_signing=False):
# Create an application envelope
# docusign_auth.DSClient.login("jwt")
account_id = session["ds_account_id"]
envelope_api = docusign_api_handler.get_envelope_api()
templates_api = docusign_api_handler.get_templates_api()
access_code = generate_access_code()
signer = Signer(
email=destination_email,
name=signer_name,
recipient_id="1",
routing_order="1",
role_name="signer",
# Use a six-character access code so URL doesn't expire
access_code=access_code,
tabs=signer_tabs
)
doc = Document(
document_base64 = base64_file_content,
name = "Your application generated by PlanProvide",
file_extension = "pdf",
document_id = 1,
# Detect Adobe form field names
transform_pdf_fields = True
)
documents = [doc]
template_req_object = EnvelopeTemplate(
documents=documents, email_subject="Please sign this document",
recipients=Recipients(signers=[signer]),
description="Template created via the API",
name="Application Template",
shared="false",
status="created"
)
try:
res = templates_api.create_template(account_id=account_id, envelope_template=template_req_object)
except Exception as e:
raise DocusignError(e)
try:
template_id = res.templates[0].template_id
except:
template_id = res.template_id
envelope_definition = EnvelopeDefinition(
email_subject="Please sign this document sent from the Python SDK",
template_id=template_id,
template_roles=[signer],
status="sent" # requests that the envelope be created and sent.
)
# Send it to an email
try:
results = envelope_api.create_envelope(account_id=account_id, envelope_definition=envelope_definition)
except Exception as e:
raise DocusignError(e)
return {
"envelope_id": results.envelope_id,
"access_code": access_code
}
As far as I can tell, the Tabs object still has only the two Text fields all the way up to the template creation, so I'm not sure why the duplicates appear. Any help or ideas with this issue would be greatly appreciated!
EDIT:
Here's where we call generate_name_date_tabs():
tabs = docusign_api_handler.generate_name_date_tabs(name, datetime.today().strftime('%m-%d-%y'))
try:
resp = application_services.create_application_envelope(
destination_email,
base64_file_content,
signer_name=name,
signer_tabs=tabs, is_embedded_signing=False)
I think I see the problem.
You're defining the tabs inside signer by providing the tabs field. Later down the code, when you're creating the envelope, you again provide the same signer in templateRoles:
except:
template_id = res.template_id
envelope_definition = EnvelopeDefinition(
email_subject="Please sign this document sent from the Python SDK",
template_id=template_id,
template_roles=[signer],
status="sent"
I'd change template_roles=[signer] to templateRoles=[{"email":"email#domain.com", "name": "name", "roleName" : "signer"}] and update
signer = Signer(
recipient_id="1",
routing_order="1",
role_name="signer",
# Use a six-character access code so URL doesn't expire
access_code=access_code,
tabs=signer_tabs
)
to not include name and email.
If that doesn't work, we'd need to dig in some more.Can you please show where you call generate_name_date_tabs?
Also can you show what's assigned to signer_tabs in the code below?
signer = Signer(
email=destination_email,
name=signer_name,
recipient_id="1",
routing_order="1",
role_name="signer",
# Use a six-character access code so URL doesn't expire
access_code=access_code,
**tabs=signer_tabs**
)
If you're seeing the issue disappearing and appearing with different releases, I might very well be a bug. Let us know if any of above is useful in narrowing down the problem.
First off, if you want a date/time when it's signed, don't use a textTab, but a dateSignedTab. That one automatically fill in the date/time when the document is signed.
Second, you are using a template. If your template has tabs define - they would be there in addition to the tabs in your code.
Third, if you don't provide location (X/Y coordinates) and no anchorText, the tab would be placed in position 0/0 or upper left corner like you see.
So, the one in the right place is probably coming from the template, the one in your code is showing in the upper left corner cause no position was specified.
I was creating the following script using Instapy:
#!/usr/bin/env python3
from instapy import InstaPy
number = int(input("How many Number of people you want to follow: "))
user = []
for i in range(0,number):
name = input("Enter Username to interact: ")
user.append(name)
session = InstaPy(username=" ",password=" ")
session.login()
#Used to Follow the User
session.set_do_follow(enabled=True, percentage=100)
#Used to comment on a post
session.set_comments(["Cool", "Super!"])
session.set_do_comment(enabled=True, percentage=80)
#Used to Like the Post of the User
session.set_do_like(True, percentage=70)
#Used to Interact with the User
session.interact_by_users(user, amount=5,randomize=True, media='Photo')
#Used to insteract by Comments
session.set_use_meaningcloud(enabled=True, license_key=' ', polarity="P")
session.set_use_yandex(enabled=True, API_key=' ', match_language=True, language_code="en")
session.set_do_reply_to_comments(enabled=True, percentage=100)
session.set_comment_replies(replies=[u"πππ", u"ππππππππͺπΌ", u"ππ", "ππ¬", u"πππππΌππΌππΌ", u"πππΌββοΈππππ", u"πππ", u"π", u"π", u"π", u"π€π€π€π€π€", u"ππΌπ"],media="Photo")
session.set_do_like(enabled=True, percentage=94)
session.interact_by_comments(user, posts_amount=10, comments_per_post=5, reply=True, interact=True, randomize=False, media="Photo")
session.end()
Whenever I try to run the script following Error displays:
Oh no! Failed to get the list of supported languages by Yandex Translate :( ~text language won't be matched
And
link_elems error local variable 'post_href' referenced before assignment
The main problem is writing comments on the post.
There are couple of issues I have found with Instapy comment. I can help you with those.
Comments will not work if any other accounts are mentioned like #nizamudheen_at
Comments will break if it is too long.
These can be fixed quickly by modifying comment_util.py (Python37_64\Lib\site-packages\instapy) little bit.
One disadvantage instapy have it uses 'Enter' button always to post comment. So we need to tweak it make it is commenting by clicking "Post". Other wise long comments will not work.
To do that:
Add a function in comment_util.py like:
def get_comment_post(browser):
comment_post = browser.find_elements_by_xpath(
read_xpath(get_comment_post.__name__, "comment_post")
)
return comment_post
And in comment_image function, make sure you add first if statement in try. This will make sure if you are mentioning any account and also if comment is longer, it is handled properly :
def comment_image(browser, username, comments, blacklist, logger, logfolder):
"""Checks if it should comment on the image"""
# check action availability
if quota_supervisor("comments") == "jump":
return False, "jumped"
rand_comment = random.choice(comments).format(username)
rand_comment = emoji.demojize(rand_comment)
rand_comment = emoji.emojize(rand_comment, use_aliases=True)
open_comment_section(browser, logger)
# wait, to avoid crash
sleep(3)
comment_input = get_comment_input(browser)
comment_post = get_comment_post(browser)
logger.info("{} pooooost".format(comment_post))
logger.info("{} pooooost".format(comment_post[0]))
try:
if len(comment_input) > 0:
# wait, to avoid crash
sleep(2)
comment_input = get_comment_input(browser)
logger.info("{} .....".format(comment_input))
logger.info("{} input[0]".format(comment_input[0]))
# below, an extra space is added to force
# the input box to update the reactJS core
comment_to_be_sent = rand_comment
# wait, to avoid crash
sleep(2)
# click on textarea/comment box and enter comment
# wait, to avoid crash
sleep(1)
if '#' in comment_to_be_sent:
(
ActionChains(browser)
.move_to_element(comment_input[0])
.click()
.send_keys(comment_to_be_sent)
.pause(3)
.move_to_element(comment_post[0])
.click()
.perform()
)
else:
# post comment / <enter>
(
ActionChains(browser)
.move_to_element(comment_input[0])
.send_keys(Keys.ENTER)
.perform()
)
update_activity(
browser,
action="comments",
state=None,
logfolder=logfolder,
logger=logger,
)
Last but not the least, add xpath function to handle "post" button:
In xpath_compile.py
xpath["get_comment_post"] = {
"comment_post": "//button[text()='Post']",
}
I am using Odoo 11 and I want to display a Warning popup in a #api.constraint method. The warning popup that I want to display has two buttons, the first is an OK button used to ignore the warning and the other one is a Cancel button used to attempt the saving operation, it' s similar to the warning popup that odoo uses like on the picture below :
I searched a lot on the web and I found different proposed solutions like using Wizard, exception.Warning() and osv.except_osv(), but unfortunately no one of this solution gives me exactly what I want.
Any help please?
You can raise warning message by different ways. I have created message related to stock quantity by this way:
if self.qty > new_qty:
message = _('You plan to sell %s quantity but you only have %s available in %s warehouse.') % \
(self.qty, self.product_id.virtual_available, self.order_id.warehouse_id.name)
mess= {
'title': _('Not enough inventory!'),
'message' : message
}
return {'warning': mess}
This return same wizard of warning as you want and as shown given image.
The basic odoo Warning that you can use is called from the odoo.exception class.
For example:
from odoo.exceptions import AccessError, UserError, RedirectWarning, ValidationError, Warning
#api.constrains('age')
def _check_something(self):
for record in self:
if record.age > 20:
raise Warning(_("Your record is too old: %s" % record.age))
This should work for your issue.
I write a (draft) module to open Dialog box see:
https://github.com/Micronaet/micronaet-sales/tree/master/confirm_dialog_wizard
In your button you can write this code to open, for ex. to hide a product:
#api.multi
def hide_product_pricelist(self):
""" Hide product
"""
return self.env['dialog.box.wizard'].open_dialog(
message='The product will be hided, <b>you cannot use again</b> '
'but remain in sale order where yet present, <br/>'
'confirm?',
action='self.env["product.product"].browse(%s).write('
'{"active": False})' % self.id,
title='Confirm request:',
mode='cancel_confirm',
)
The program will pop up a window to confirm (as in tree you cannot use "confirm" message parameter), I'm try to do better but ... its a begin ... :)
It is similar to the warning shown when we use the confirm attribute on a button.
<button confirm="Reset to draft!"/>
Raising a validation error or returning a warning as dictionary did not show the Cancel button.
I copied and pasted code into my IDE (TextWrangler). Now when I try to run my code, I get a ton of random errors regarding indentation and invalid syntax.
The code worked perfectly before I copied & pasted it from one Django view into another. I'm almost 100% sure the code is still correct in my new view, however, every time it runs I'll get a ton of errors relating to indentation and invalid syntax (even multiline comments like ''' trigger an "invalid syntax on line 234" error.
I've tried switching IDE's over to sublime, and even backspacing all indentations and then retabbing them to no avail. Each time I fix an "error" on one line, a new error on another line is created.
My code is below, please let me know any thoughts on how to fix.
#require_POST
def pay(request):
if request.method == 'POST':
form = CustomerForm(request.POST)
if form.is_valid():
# If the form has been submitted...
# All validation rules pass
#get the customer by session'd customer_id
c = get_object_or_404(Customer, pk = request.session['customer_id'])
#assign shipping info from POST to the customer object
c.first_name = request.POST['first_name']
c.last_name = request.POST['last_name']
c.street_address = request.POST['street_address']
c.city = request.POST['city']
c.state = request.POST['state']
c.zip = request.POST['zip']
#assign email info from POST to the customer object
c.email_address = request.POST['email_address']
stripe.api_key = REDACTED
# Get the credit card details submitted by the form
token = request.POST['stripeToken']
#tries to save the newly added form data.
try:
#save the new customer object's data
c.save()
########## THIS HANDLES CREATING A NEW STRIPE PAYMENT ################
# Create a Customer
try:
customer = stripe.Customer.create(
card=token,
plan="monthly",
email= c.email_address)
#need to save customer's id (ex: c.stripe_id = token.id)
#if there's a token error
except stripe.error.InvalidRequestError, e:
pass
#if the card is declined by Stripe
except stripe.error.CardError, e:
body = e.json_body
err = body['error']
print "Status is: %s" % e.http_status
print "Type is: %s" % err['type']
print "Code is: %s" % err['code']
# param is '' in this case
print "Param is: %s" % err['param']
print "Message is: %s" % err['message']
except stripe.error.AuthenticationError, e:
# Authentication with Stripe's API failed
# (maybe you changed API keys recently)
pass
except stripe.error.APIConnectionError, e:
# Network communication with Stripe failed
pass
except stripe.error.StripeError, e:
# Display a very generic error to the user, and maybe send
# yourself an email
pass
except Exception, e:
# Something else happened, completely unrelated to Stripe
pass
return render(request, 'shipment/confirm.html', {'date' : 'April 15, 2014'})
#passes the context to the template for confirming the customer's data
#context = { 'email_address' : c.email_address, 'first_name' : c.first_name,
# 'last_name' : c.last_name, 'street_address' : c.street_address,
# 'city' : c.city, 'state' : c.state, 'zip' : c.zip, }
#return render(request, 'shipment/pay.html', context)
#If there is a duplicate email it redirects the user back to the form with no error message.
#If anything else happens, it redirects the user back to the form.
else:
form = CustomerForm() # An unbound form
return render(request, 'shipment/createAccount.html', { 'form': form } )
Here's a couple of screenshots of your code in my editor with tabs (set to 4) and space characters shown in a reddish color. As you can see it contains quite a hodgepodge of the two on many lines. Python is very whitespace sensitive and it's important to be consistent. This is usually handled by configuring your editor to always convert tabs to n whitespace characters (or vice versa, but the former is often preferred).
To fix your problem, re-indent everything using a single method. My editor also has a convert-tabs-to-spaces command which could be used first to simplify the task somewhat.
This is why you should use soft tabs instead of hard tabs. You have at least one line that mixes them (check out the line with c.save()), looking at the edit version of your code. Change your IDE settings to always use spaces or tabs (if you haven't already), I recommend spaces.
See this question for how to view whitespace in sublime to find the offending tab character.
I am REALLY confused. I'm basically trying to fill out a form on a website with mechanize for python. I got everything to work except the dropdown menu. What do I use to select it and what do I put for the value? I don't know if I'm supposed to put the name of the selection or the numerical value of it. Help would be greatly appreciated, thanks.
Code snippet:
try:
br.open("http://www.website.com/")
try:
br.select_form(nr=0)
br['number'] = "mynumber"
br['from'] = "herpderp#gmail.com"
br['subject'] = "Yellow"
br['carrier'] = "203"
br['message'] = "Hello, World!"
response = br.submit()
except:
pass
except:
print "Couldn't connect!"
quit
I'm having trouble with the carrier, which is a dropdown menu.
According to the mechanize documentation examples, you need to access attributes of the form object, not the browser object. Also, for the select control, you need to set the value to a list:
br.open("http://www.website.com/")
br.select_form(nr=0)
form = br.form
form['number'] = "mynumber"
form['from'] = "herpderp#gmail.com"
form['subject'] = "Yellow"
form['carrier'] = ["203"]
form['message'] = "Hello, World!"
response = br.submit()
Sorry for reviving a long-dead post, but this was the still best answer I could find on google and it doesn't work. After more time than I care to admit, I figured it out. infrared is right about the form object, but not about the rest, and his code doesn't work. Here's some code that works for me (though I'm sure a more elegant solution exists):
# Select the form
br.open("http://www.website.com/")
br.select_form(nr=0) # you might need to change the 0 depending on the website
# find the carrier drop down menu
control = br.form.find_control("carrier")
# loop through items to find the match
for item in control.items:
if item.name == "203":
# it matches, so select it
item.selected = True
# now fill out the rest of the form and submit
br.form['number'] = "mynumber"
br.form['from'] = "herpderp#gmail.com"
br.form['subject'] = "Yellow"
br.form['message'] = "Hello, World!"
response = br.submit()
# exit the loop
break