From d4025eba7be5ca7691eb1602208cea6b80138f18 Mon Sep 17 00:00:00 2001 From: jsfehler Date: Wed, 26 Jun 2024 09:07:25 -0400 Subject: [PATCH] docs: Tweak examples in docstrings to be valid doctest code and executable against the test app (#1306) --- splinter/abc/cookie_manager.py | 49 +++++++++++++++++++--------------- splinter/driver/__init__.py | 45 +++++++++++++++++-------------- splinter/element_list.py | 7 ++++- splinter/exceptions.py | 12 +++++++-- 4 files changed, 68 insertions(+), 45 deletions(-) diff --git a/splinter/abc/cookie_manager.py b/splinter/abc/cookie_manager.py index 13d4d09e1..a41153002 100644 --- a/splinter/abc/cookie_manager.py +++ b/splinter/abc/cookie_manager.py @@ -3,36 +3,40 @@ # license that can be found in the LICENSE file. from abc import ABC from abc import abstractmethod +from typing import Dict class CookieManagerAPI(ABC): """Specification for how a Splinter driver handles cookies. - A CookieManager acts like a ``dict``, so you can access the value of a - cookie through the [] operator, passing the cookie identifier: + CookieManager implementations are driver-specific. + They should not be created by the end-user. To access a CookieManager, + drivers should implement a `cookies` attribute containing a CookieManager. - Examples: + CookieManager has behaviour similar to a ``dict``, thus + you should get the value of a cookie using the [] operator: - >>> cookie_manager.add({'name': 'Tony'}) - >>> assert cookie_manager['name'] == 'Tony' + Example: + + >>> browser.cookies.add({'name': 'Tony'}) + >>> assert browser.cookies['name'] == 'Tony' """ def __init__(self, driver) -> None: self.driver = driver @abstractmethod - def add(self, cookie, **kwargs) -> None: + def add(self, cookie: Dict[str, str], **kwargs) -> None: """Add a cookie. - Extra arguments will be used to build the cookie. - Arguments: - cookie (dict): Each key is an identifier for the cookie value. + cookie: A key/value pair containing the cookie's name and value. + kwargs: Driver-specific extra arguments to build the cookie with. - Examples: + Example: - >>> cookie_manager.add({'name': 'Tony'}) - >>> browser.cookies.add({'cookie_name': 'cookie_value'}, path='/cookiePath') + >>> browser.cookies.add({'cookie_name': 'cookie_value'}, path='/') + >>> assert browser.cookies['cookie_name'] == 'cookie_value' """ raise NotImplementedError @@ -40,14 +44,16 @@ def add(self, cookie, **kwargs) -> None: def delete(self, *cookies: str) -> None: """Delete one or more cookies. + If the cookie does not exist, this function has no effect. + Arguments: cookies (str): Identifiers for each cookie to delete. - Examples: + Example: - >>> cookie_manager.delete( - 'name', 'birthday', 'favorite_color') # deletes these three cookies - >>> cookie_manager.delete('name') # deletes one cookie + >>> browser.cookies.delete('name', 'birthday', 'favorite_color') + >>> browser.cookies.delete('name') + >>> assert 'name' not in browser.cookies.all().keys() """ raise NotImplementedError @@ -65,11 +71,10 @@ def all(self, verbose: bool = False): # NOQA: A003 drivers, it won't make any difference). In this case, this method will return a list of dicts, each with one cookie's info. - Examples: + Example: - >>> cookie_manager.add({'name': 'Tony'}) - >>> cookie_manager.all() - [{'name': 'Tony'}] + >>> browser.cookies.add({'name': 'Tony'}) + >>> result = browser.cookies.all() Returns: All the available cookies. @@ -77,11 +82,11 @@ def all(self, verbose: bool = False): # NOQA: A003 raise NotImplementedError @abstractmethod - def __contains__(self, key) -> bool: + def __contains__(self, key: str) -> bool: raise NotImplementedError @abstractmethod - def __getitem__(self, item): + def __getitem__(self, item: str): raise NotImplementedError @abstractmethod diff --git a/splinter/driver/__init__.py b/splinter/driver/__init__.py index a57ea263f..b87d25abe 100644 --- a/splinter/driver/__init__.py +++ b/splinter/driver/__init__.py @@ -364,16 +364,17 @@ def choose(self, name: str, value: str) -> None: def check(self, name: str) -> None: """Check a checkbox by its name. + If you call ``browser.check`` n times, the checkbox keeps checked, it never get unchecked. + + To uncheck a checkbox, see the :meth:`uncheck ` method. + Arguments: name (str): name of the element to check. Example: - >>> browser.check("agree-with-terms") + >>> browser.check("some-check") - If you call ``browser.check`` n times, the checkbox keeps checked, it never get unchecked. - - To uncheck a checkbox, take a look in the :meth:`uncheck ` method. """ raise NotImplementedError( "%s doesn't support checking elements." % self.driver_name, @@ -387,7 +388,7 @@ def uncheck(self, name: str) -> None: Example: - >>> browser.uncheck("send-me-emails") + >>> browser.uncheck("some-check") If you call ``brower.uncheck`` n times, the checkbox keeps unchecked, it never get checked. @@ -408,7 +409,7 @@ def select(self, name: str, value: str) -> None: Example: - >>> browser.select("state", "NY") + >>> browser.select("pets", "cat") """ raise NotImplementedError( "%s doesn't support selecting options in 'select' element." % self.driver_name, @@ -732,15 +733,14 @@ def cookies(self) -> Type[CookieManagerAPI]: class ElementAPI: - """ - Basic element API class. + """Basic element API class. Any element in the page can be represented as an instance of ``ElementAPI``. Once you have an instance, you can easily access attributes like a ``dict``: - >>> element = browser.find_by_id("link-logo").first - >>> assert element['href'] == 'https://splinter.readthedocs.io' + >>> element = browser.find_by_id("foo").first + >>> assert element['href'] == 'http://localhost:5000/foo' You can also interact with the instance using the methods and properties listed below. """ @@ -769,20 +769,24 @@ def click(self) -> None: raise NotImplementedError def check(self) -> None: - """ - Check the element, if it's "checkable" (e.g.: a checkbox). + """Check the element, if it's "checkable" (e.g.: a checkbox). If the element is already checked, this method does nothing. For unchecking elements, take a loot in the :meth:`uncheck ` method. + + Example: + >>> browser.find_by_css("[name='some-check']").uncheck() """ raise NotImplementedError def uncheck(self) -> None: - """ - Uncheck the element, if it's "checkable" (e.g.: a checkbox). + """Uncheck the element, if it's "checkable" (e.g.: a checkbox). If the element is already unchecked, this method does nothing. For checking elements, take a loot in the :meth:`check ` method. + + Example: + >>> browser.find_by_css("[name='some-check']").uncheck() """ raise NotImplementedError @@ -792,10 +796,11 @@ def checked(self) -> bool: Example: - >>> element.check() - >>> assert element.checked - >>> element.uncheck() - >>> assert not element.checked + >>> elem = browser.find_by_css("[name='some-check']") + >>> elem.check() + >>> assert elem.checked + >>> elem.uncheck() + >>> assert not elem.checked """ raise NotImplementedError @@ -866,7 +871,7 @@ def type(self, value: str, slowly: bool = False) -> str: # NOQA: A003 Example: >>> from selenium.webdriver.common.keys import Keys - >>> ElementAPI.type(Keys.RETURN) + >>> browser.find_by_css("[name='q']").type(Keys.RETURN) """ raise NotImplementedError @@ -877,7 +882,7 @@ def select(self, value: str, slowly: bool = False) -> None: Example: - >>> element.select("NY") + >>> browser.find_by_css("[name='pets']").select("cat") """ raise NotImplementedError diff --git a/splinter/element_list.py b/splinter/element_list.py index c68f57a2e..812be01cc 100644 --- a/splinter/element_list.py +++ b/splinter/element_list.py @@ -19,7 +19,10 @@ class ElementList: access a non-existent item: >>> element_list = ElementList([]) - >>> element_list[0] # raises ElementDoesNotExist + >>> try: + ... element_list[0] + ... except ElementDoesNotExist: + ... pass """ def __init__( @@ -52,6 +55,7 @@ def first(self): Example: + >>> element_list = browser.find_by_css('input') >>> assert element_list[0] == element_list.first """ return self[0] @@ -62,6 +66,7 @@ def last(self): Example: + >>> element_list = browser.find_by_css('input') >>> assert element_list[-1] == element_list.last """ return self[-1] diff --git a/splinter/exceptions.py b/splinter/exceptions.py index 8d735aa65..d715242d9 100644 --- a/splinter/exceptions.py +++ b/splinter/exceptions.py @@ -10,7 +10,12 @@ class DriverNotFoundError(Exception): Example: >>> from splinter import Browser - >>> b = Browser('unknown driver') # raises DriverNotFoundError + >>> + >>> + >>> try: + ... b = Browser('unknown driver') + ... except DriverNotFoundError: + ... pass """ pass @@ -26,7 +31,10 @@ class ElementDoesNotExist(Exception): Example: >>> elements = browser.find_by_id('unknown-id') # returns an empty list - >>> elements[0] # raises ElementDoesNotExist + >>> try: + ... elements[0] + ... except ElementDoesNotExist: + ... pass """ pass