Subclassed object results in NoneType - python

I'm trying to subclass the Chrome WebDriver to include some initialization and cleanup code, but then Python complains that the created object is set to None:
import glob
import selenium
import subprocess
from selenium.webdriver.common.by import By
class WebDriver(selenium.webdriver.Chrome):
def __init__(self, url, *args, **kwargs):
super().__init__(*args, **kwargs)
self.url = url
def __enter__(self):
self.get(self.url)
self.implicitly_wait(15)
def __exit__(self, type, value, traceback):
self.quit()
for path in glob.glob('/tmp/.org.chromium.Chromium.*'):
subprocess.run(['rm', '-rf', path], check=True)
with WebDriver('https://google.com') as driver:
driver.find_element(By.ID, 'lst-ib').send_keys('Search')
Running the code with Python 3:
$ python3 test.py
Traceback (most recent call last):
File "test.py", line 43, in <module>
driver.find_element(By.ID, 'lst-ib').send_keys('Search')
AttributeError: 'NoneType' object has no attribute 'find_element'

Your __enter__() magic method should return self for the driver variable to be pointed to the instance of the WebDriver class:
def __enter__(self):
self.get(self.url)
self.implicitly_wait(15)
return self
To get more information about why and how this works, please see:
Understanding Python's "with" statement
Explaining Python's '__enter__' and '__exit__'

Related

How can I implement options in my oop python code?

Help me, I don't know how can I implement options in my oop code, I don't want browser pop up every time I run the code, I have to add headless option but I don't know how
I do know how to make my code headless in functional or imperative paradigm, but I can't figure out how to implement this in oop paradigm, whatever I do, I approach to an error, I don't know what to do, I would be extremely thankful to who guild me to light
my code
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import os
os.environ["PATH"] = "C:\\SeleniumWebDrivers"
op = webdriver.ChromeOptions()
op.add_argument("--disable-blink-features=AutomationControlled")
op.add_argument("headless")
class Avamovie(webdriver.Opera(options=op)):
def __init__(self, teardown=False):
self.teardown = teardown
super(Avamovie, self).__init__()
self.implicitly_wait(15)
self.maximize_window()
self.minimize_window()
def __exit__(self, exc_type, exc_val, exc_tb) -> None:
if self.teardown:
self.quit()
def get_the_page(self):
self.get("https://avamovie17.xyz")
def search_box(self, title):
sbox = self.find_element_by_css_selector("input[placeholder='جستجو']")
sbox.send_keys(title)
sbox.click()
r = self.find_element_by_css_selector("ul[class='search_result_list']")
r = r.find_element_by_tag_name("li").find_element_by_css_selector(
"span[class='title']"
)
r.click()
def download_links(self):
links = self.find_elements_by_css_selector("a[href*='.mkv']")
links = [link.get_attribute("href") for link in links]
print(links)
with Avamovie() as scraper:
scraper.get_the_page()
scraper.search_box("A hero 2021")
scraper.download_links()
my latest error:
Traceback (most recent call last):
File "c:\Users\yasin\Desktop\pf\Projects\Selena\selena.py", line 1, in <module>
from sites.avamovie import Avamovie
File "c:\Users\yasin\Desktop\pf\Projects\Selena\sites\avamovie.py", line 10, in <module>
class Avamovie(webdriver.Opera(options=op)):
File "C:\Users\yasin\AppData\Roaming\Python\Python310\site-packages\selenium\webdriver\opera\webdriver.py", line 79, in __init__
OperaDriver.__init__(self, executable_path=executable_path,
File "C:\Users\yasin\AppData\Roaming\Python\Python310\site-packages\selenium\webdriver\opera\webdriver.py", line 55, in __init__
ChromiumDriver.__init__(self,
File "C:\Users\yasin\AppData\Roaming\Python\Python310\site-packages\selenium\webdriver\chrome\webdriver.py", line 73, in __init__
self.service.start()
File "C:\Users\yasin\AppData\Roaming\Python\Python310\site-packages\selenium\webdriver\common\service.py", line 71, in start
cmd.extend(self.command_line_args())
File "C:\Users\yasin\AppData\Roaming\Python\Python310\site-packages\selenium\webdriver\chrome\service.py", line 45, in command_line_args
return ["--port=%d" % self.port] + self.service_args
TypeError: %d format: a real number is required, not dict
I would appreciate any help, thanks guys
You appear to be trying to inherit from an instance of Opera, not the class itself. The options are passed to the call to super().__init__.
class Avamovie(webdriver.Opera):
def __init__(self, options, teardown=False):
self.teardown = teardown
super(Avamovie, self).__init__(options)
self.implicitly_wait(15)
self.maximize_window()
self.minimize_window()
...
with Avamovie(op) as scraper:
scraper.get_the_page()
scraper.search_box("A hero 2021")
scraper.download_links()

AttributeError: 'Context' object has no attribute 'app'

Hello I did not found answer for similar problem so I add new topic.
I have problem with bdd + appium using a page object model. When I run my script I have issue:
Traceback (most recent call last):
File "/home/mimy/.local/lib/python3.8/site-packages/behave/model.py", line 1329, in run
match.run(runner.context)
File "/home/mimy/.local/lib/python3.8/site-packages/behave/matchers.py", line 98, in run
self.func(context, *args, **kwargs)
File "features/steps/allow_to_app_steps.py", line 6, in tap_allow_when_using_app
context.app.launch_page.tap_allow_button()
File "/home/mimy/.local/lib/python3.8/site-packages/behave/runner.py", line 321, in __getattr__
raise AttributeError(msg)
AttributeError: 'Context' object has no attribute 'app'
My environment.py file looks like this:
from appium import webdriver
from app.application import Application
def before_scenario(context, scenario):
desired_capabilities = {
"platformName": "Android",
"platformVersion": "10",
"deviceName": "Pixel 2 XL",
"appPackage": "com.xxx.xxx",
"appActivity": ".ui.MainActivity",
"automationName": "UiAutomator2"
}
context.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_capabilities=desired_capabilities)
context.driver.implicitly_wait(5)
context.app = Application(context.driver)
def after_scenario(context, scenario):
context.driver.quit()
My steps file looks like this:
from behave import given, when, then, step
#given('I click on the "Allow only while using the app" button')
def tap_allow_when_using_app(context):
context.app.launch_page.tap_allow_button()
#when('I click on the "Allow" button')
def tap_allow(context):
context.app.launch_page.tap_allow()
My pages file for my page object model looks like:
###LunchPage###
from selenium.webdriver.common.by import By
from pages.base_page import Page
class LaunchPage(Page):
dialog_title = (By.XPATH, "//android.widget.TextView[contains(#text,'Allow QSpot to access this device')]")
allow_only_while_using_the_app = (By.XPATH, "//android.widget.Button[#text='Allow only while using the app']")
allow = (By.XPATH, "//android.widget.Button[#text='Allow']")
def tap_allow_button(self):
self.click(*self.allow_only_while_using_the_app)
def tap_allow(self):
self.click(*self.allow)
###BasePage###
class Page:
def __init__(self, driver):
self.driver = driver
def find_element(self, *locator):
return self.driver.find_element(*locator)
def click(self, *locator):
e = self.find_element(*locator)
e.click()
And class Application
from pages.launch_page import LaunchPage
class Application:
def __init__(self, driver):
self.launch_page = LaunchPage(driver)
As I now this issue may be related with "driver was not starting" but I am not able to fix it.
Many thanks for help!
In my case, I missed up names in architecture names.
So after changing from "enviroment" to "environment" (missing N).
it became alive.

AttributeError: 'LoginPage' object has no attribute 'driver'

I have a base class. Inheriting base class, login.py runs without any problem. But when I run Company_Management.py its giving me:
Traceback (most recent call last):
File "/home/sohel/eclipse-workspace/Copell/copell/Company_Management.py", line 22, in test_company
em.test_logn()
File "/home/sohel/eclipse-workspace/Copell/copell/login.py", line 15, in test_logn
driver =self.driver
AttributeError: 'LoginPage' object has no attribute 'driver'
What I am trying to do is that, when I will run Company_Management.py it will excute test_logn(self) method first then will click on 2 urls from xpath.
base.py
import unittest
import time
from selenium import webdriver
class Login(unittest.TestCase):
#classmethod
def setUpClass(cls):
cls.driver = webdriver.Chrome('/home/sohel/eclipse-workspace/chromedriver')
cls.driver.maximize_window()
cls.driver.get("https:www.car.com/login?back_url=%2F")
time.sleep(3)
#classmethod
def tearDownClass(cls):
cls.driver.close()
if __name__ == '__main__':
unittest.main()
login.py
import base
import unittest
import time
class LoginPage(base.Login):
def test_logn(self):
driver =self.driver
driver.find_element_by_id("email").clear()
driver.find_element_by_id("email").send_keys("keya#gmail.com")
driver.find_element_by_id("password").clear()
driver.find_element_by_id("password").send_keys("Abcd1234")
driver.find_element_by_xpath("//button[#type='submit']").click()
def test_logout(self):
self.driver.find_element_by_xpath("//li[9]/a/span").click()
if __name__ == '__main__':
unittest.main()
Company_Management.py
import base
import unittest
import login
import logging
import time
class CompanyManagement(base.Login):
def test_company(self):
driver = self.driver
em = login.LoginPage()
em.test_logn()
driver.find_element_by_xpath("//ec-ui-side-bar/div/div/ul/li[3]/a/span").click()
driver.find_element_by_xpath("//ec-ui-side-bar/div/div/ul/li[3]/ul/li/a/span").click()
time.sleep(3)
if __name__ == '__main__':
unittest.main()
ERROR: test_company (copell.Company_Management.CompanyManagement) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/sohel/eclipse-workspace/Copell/copell/Company_Management.py", line 22, in test_company em.test_logn() File "/home/sohel/eclipse-workspace/Copell/copell/login.py", line 15, in test_logn driver =self.driver AttributeError: 'LoginPage' object has no attribute 'driver' --------------------------------------------------------------------- Ran 1 test in 7.227s FAILED (errors=1)
Both your classes extend [Python 2]: class unittest.TestCase(methodName='runTest').
According to [Python 2]: Skipping tests and expected failures
Skipped tests will not have setUp() or tearDown() run around them. Skipped classes will not have setUpClass() or tearDownClass() run.
Also, according to [Python 2]: setUpClass and tearDownClass:
If you want the setUpClass and tearDownClass on base classes called then you must call up to them yourself.
What happens:
login.py: LoginPage is instantiated (and run) automatically by the unittest framework (unittest.main()) and setUpClass method is called -
which adds the driver attribute to the LoginPage class - and (automatically, to) all its instances
Company_Management.py: LoginPage is instantiated manually by you (em = login.LoginPage()), but the setUpClass method isn't called - and thus LoginPage (or any of its instances) doesn't have the driver attribute - hence your error. To fix it, manually call the method yourself, either:
After instantiating the class (on the instance):
em = login.LoginPage()
em.setUpClass()
On the class itself (better, before instantiating it)
login.LoginPage.setUpClass()
em = login.LoginPage()

Redirect unknown attributes

I'm building a custom class to add feautures to selenium.webdriver.Chrome on Python 3.6.2.
from selenium import webdriver
class MyChrome:
def __init__(self):
self.mydriver = webdriver.Chrome()
So far, beside some custom methods I made myself, I used to overridden some selenium.webdriver.Chrome very standard methods like this:
def get(self, url):
self.mydriver.get(url)
Since I don't want to waste time rewriting like that methods like get, find_element_by_xpath, etc... that already works fine for me I tried the following, as suggested here and here
def __getattr__(self, name, *args, **kwargs):
return getattr(self.mydriver, name)(*args, **kwargs)
But when I run the following code
from selenium import webdriver
class MyChrome:
def __init__(self):
self.mydriver = webdriver.Chrome()
def __getattr__(self, name, *args, **kwargs):
return getattr(self.mydriver, name)(*args, **kwargs)
chrome = MyChrome()
chrome.get('https://stackoverflow.com/')
I encounter the error
Traceback (most recent call last):
File "MyChrome.py", line 11, in <module>
chrome.get('https://stackoverflow.com/')
File "MyChrome.py", line 8, in __getattr__
return getattr(self.mydriver, name)(*args, **kwargs)
TypeError: get() missing 1 required positional argument: 'url'
How do I redirect calls to unknown methods called on my object chrome to it's instance variable self.driver?
I created a custom Webdriver once to add features to selenium Chrome Webdriver and I did that by subclassing selenium Chrome Webdriver. This way you inherit all the webdriver methods without a getattr
from selenium.webdriver import Chrome
class MyChrome(Chrome):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# add all your custom features
It doesn't provide answer to your question but something you can leverage

insert() got an unexpected keyword argument 'data'

I am learning monogoDB, I am beginner but I am facing some errors. What is my coding error and tell me the solution for that?
this is post.py file
import uuid
from database import Database
import datetime
class Post (object):
def __init__(self,blog_id,title,content,author,date=datetime.datetime.utcnow(),id=None):
self.blog_id=blog_id
self.title=title
self.content=content
self.author=author
self.created_date=date
self.id=uuid.uuid4().hex if id is None else id
def save_to_mongo(self):
Database.insert(collection='students',data=self.json())
def json(self):
return {
'id':self.id,
'blog_id':self.blog_id,
'author':self.author,
'content':self.content,
'title':self.title,
'created_date':self.created_date
}
#staticmethod
def from_mongo(id):
return Database.find_one(collection='students',query={'id':id})
#staticmethod
def from_blog(id):
return [post for post in Database.find(collection='students',query={'blog_id':id})]
database.py file
import pymongo
class Database(object):
URI="mongodb//127.0.0.1:27017"
DATABASE=None
#staticmethod
def initialize():
client=pymongo.MongoClient(Database.URI)
Database.DATABASE=client['local']
#staticmethod
def insert(collection,data):
Database.DATABASE[collection].insert(data)
#staticmethod
def insert(collection,query):
return Database.DATABASE[collection].find(data)
#staticmethod
def insert(collection,query):
return Database.DATABASE[collection].find_one(data)
this is test.py file
from database import Database
from post import Post
Database.initialize()
post=Post(blog_id="123",title="Anoother great post",content="This is some
sample content",author="rahul")
post.save_to_mongo()
i got the following error during running test.py
[Running] python "d:\myprograms\python\test.py"
Traceback (most recent call last):
File "d:\myprograms\python\test.py", line 9, in <module>
post.save_to_mongo()
File "d:\myprograms\python\post.py", line 15, in save_to_mongo
Database.insert(collection='students',data=self.json())
TypeError: insert() got an unexpected keyword argument 'data'

Categories