Skip to content

Commit

Permalink
Merge pull request #45 from jacebrowning/refactor-prompts
Browse files Browse the repository at this point in the history
Refactor prompts
  • Loading branch information
jacebrowning committed Dec 26, 2020
2 parents b6b614f + 07ca355 commit 71ce6c5
Show file tree
Hide file tree
Showing 12 changed files with 185 additions and 190 deletions.
6 changes: 3 additions & 3 deletions notebooks/profile_default/startup/ipython_startup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import atexit as _atexit

import pomace
from pomace import utils as _utils
from pomace import prompts as _prompts, utils as _utils
from pomace.config import settings
from pomace.models import Page, autopage
from pomace.shared import browser
Expand Down Expand Up @@ -36,8 +36,8 @@ def _display_settings():
_atexit.register(_utils.quit_browser)
_configure_logging()
_display_settings()
_utils.prompt_for_browser_if_unset()
_utils.prompt_for_url_if_unset()
_prompts.browser_if_unset()
_prompts.url_if_unset()
_utils.launch_browser()

page = autopage()
10 changes: 5 additions & 5 deletions pomace/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@

import log

from . import models, utils
from . import models, prompts, types, utils
from .config import settings


__all__ = ["fake", "prompt", "visit"]


fake = utils.Fake()
fake = types.Fake()


def visit(
Expand All @@ -24,12 +24,12 @@ def visit(
if url:
settings.url = url
else:
utils.prompt_for_url_if_unset()
prompts.url_if_unset()

if browser:
settings.browser.name = browser.lower()
else:
utils.prompt_for_browser_if_unset()
prompts.browser_if_unset()

if headless is not None:
settings.browser.headless = headless
Expand All @@ -45,5 +45,5 @@ def visit(

def prompt(*names):
for name in names:
utils.prompt_for_secret_if_unset(name)
prompts.secret_if_unset(name)
return settings
7 changes: 4 additions & 3 deletions pomace/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from cleo import Application, Command
from IPython import embed

from . import models, shared, utils
from . import models, prompts, shared, utils
from .config import settings


Expand All @@ -17,8 +17,9 @@ def handle(self):
log.init(verbosity=self.io.verbosity + 1)
log.silence("datafiles", allow_warning=True)
self.update_settings()
utils.prompt_for_browser_if_unset()
utils.prompt_for_url_if_unset()
prompts.browser_if_unset()
domains = list(set(p.domain for p in models.Page.objects.all()))
prompts.url_if_unset(domains)
utils.launch_browser()
utils.locate_models()
try:
Expand Down
51 changes: 14 additions & 37 deletions pomace/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from splinter.driver.webdriver import WebDriverElement
from splinter.exceptions import ElementDoesNotExist

from . import shared
from . import prompts, shared
from .config import settings
from .enums import Mode, Verb
from .types import URL
Expand Down Expand Up @@ -65,14 +65,14 @@ class Action:
name: str = ""
locators: List[Locator] = field(default_factory=lambda: [Locator()])

@property
def locators_sorted(self) -> List[Locator]:
return [x for x in sorted(self.locators, reverse=True) if x]

@property
def _verb(self) -> Verb:
return Verb(self.verb)

@property
def _sorted_locators(self) -> List[Locator]:
return [x for x in sorted(self.locators, reverse=True) if x]

def __post_init__(self):
if self.verb and len(self.locators) <= 1:
for mode, value in self._verb.get_default_locators(self.name):
Expand All @@ -86,50 +86,27 @@ def __bool__(self) -> bool:

def __call__(self, *args, **kwargs) -> "Page":
page = kwargs.pop("_page", None)
locator = kwargs.pop("_locator", "")

if "=" in locator:
mode, value = locator.split("=", 1)
self.locators.insert(0, Locator(mode, value))
self.datafile.save()

page = self._call_method(page, locator, *args, **kwargs)
page = self._call_method(page, *args, **kwargs)
self.datafile.save()
page.clean()

return page

def _call_method(self, page, locator, *args, **kwargs) -> "Page":
while self._finding_locator(*args, **kwargs):
def _call_method(self, page, *args, **kwargs) -> "Page":
while self._trying_locators(*args, **kwargs):
log.error(f"No locators able to find {self.name!r}")

if locator or not shared.cli:
break

choices = ["<cancel>"] + [mode.value for mode in Mode]
command = shared.cli.Bullet(
prompt="\nSelect element locator: ",
bullet=" ● ",
choices=choices,
)
mode = command.launch()
if mode == "<cancel>":
print()
mode, value = prompts.mode_and_value()
if mode:
self.locators.append(Locator(mode, value))
else:
break

command = shared.cli.Input("\nValue to match: ")
value = command.launch()
print()

self.locators.append(Locator(mode, value))

if page and self._verb.updates:
return page

return autopage()

def _finding_locator(self, *args, **kwargs) -> bool:
for locator in self.locators_sorted:
def _trying_locators(self, *args, **kwargs) -> bool:
for locator in self._sorted_locators:
if locator:
log.debug(f"Using {locator} to find {self.name!r}")
element = locator.find()
Expand Down
77 changes: 77 additions & 0 deletions pomace/prompts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import os
from typing import Tuple

from . import browser, enums, shared
from .config import settings


def browser_if_unset():
if settings.browser.name:
return

if "CI" in os.environ or not shared.cli:
settings.browser.name = os.getenv("BROWSER", "firefox")
return

command = shared.cli.Bullet(
prompt="\nSelect a browser for automation: ",
bullet=" ● ",
choices=browser.NAMES,
)
value = command.launch()
print()
settings.browser.name = value.lower()


def url_if_unset(domains=None):
if settings.url:
return

if "CI" in os.environ or not shared.cli:
settings.url = "http://example.com"
return

if domains:
command = shared.cli.Bullet(
prompt="\nStarting domain: ", bullet=" ● ", choices=domains
)
else:
command = shared.cli.Input(prompt="\nStarting domain: ", strip=True)
value = command.launch()
print()
settings.url = f"https://{value}"


def secret_if_unset(name: str):
if settings.get_secret(name, _log=False):
return

if "CI" in os.environ or not shared.cli:
settings.set_secret(name, "<unset>")
return

command = shared.cli.Input(prompt=f"{name}: ")
value = command.launch()
print()
settings.set_secret(name, value)


def mode_and_value() -> Tuple[str, str]:
if not shared.cli:
return "", ""

choices = ["<cancel>"] + [mode.value for mode in enums.Mode]
command = shared.cli.Bullet(
prompt="\nSelect element locator: ",
bullet=" ● ",
choices=choices,
)
mode = command.launch()
if mode == "<cancel>":
print()
return "", ""

command = shared.cli.Input("\nValue to match: ")
value = command.launch()
print()
return mode, value
33 changes: 33 additions & 0 deletions pomace/tests/test_prompts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# pylint: disable=expression-not-assigned,unused-variable,redefined-outer-name,unused-argument

from .. import config, prompts


def describe_browser_if_unset():
def when_ci(expect, monkeypatch):
monkeypatch.setenv("CI", "true")
config.settings.browser.name = ""
prompts.browser_if_unset()
expect(config.settings.browser.name) == "firefox"

def when_ci_and_override(expect, monkeypatch):
monkeypatch.setenv("CI", "true")
monkeypatch.setenv("BROWSER", "chrome")
config.settings.browser.name = ""
prompts.browser_if_unset()
expect(config.settings.browser.name) == "chrome"


def describe_url_if_unset():
def when_ci(expect, monkeypatch, mockbrowser):
monkeypatch.setenv("CI", "true")
config.settings.url = ""
prompts.url_if_unset()
expect(config.settings.url) == "http://example.com"


def describe_secret_if_unset():
def when_ci(expect, monkeypatch, mockbrowser):
monkeypatch.setenv("CI", "true")
prompts.secret_if_unset("foobar")
expect(config.settings.get_secret("foobar")) == "<unset>"
23 changes: 22 additions & 1 deletion pomace/tests/test_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import pytest

from ..types import URL
from ..types import URL, Fake


@pytest.fixture
Expand Down Expand Up @@ -80,3 +80,24 @@ def when_provided(expect, url):
def when_containing_slashes(expect, url):
url = URL("http://example.com/signup/#/step/2/")
expect(url.fragment) == "step_2"


def describe_fake():
@pytest.fixture(scope="session")
def fake():
return Fake()

def it_includes_zip_code(expect, fake):
print(repr(fake.zip_code))
expect(fake.zip_code).isinstance(str)

def describe_person():
def it_includes_name_in_email(expect, fake):
person = fake.person
expect(person.email).icontains(person.last_name)

def it_includes_honorific(expect, fake):
expect(fake.person.honorific).isinstance(str)

def it_includes_county(expect, fake):
expect(fake.person.county).isinstance(str)
56 changes: 0 additions & 56 deletions pomace/tests/test_utils.py

This file was deleted.

18 changes: 18 additions & 0 deletions pomace/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from typing import Optional
from urllib.parse import urlparse

import faker
import zipcodes
from parse import parse

Expand Down Expand Up @@ -135,3 +136,20 @@ def random(cls, fake) -> "Person":
place["county"],
place["zip_code"],
)


class Fake:
def __init__(self):
self.generator = faker.Faker()

def __getattr__(self, name):
method = getattr(self.generator, name)
return method()

@property
def person(self) -> Person:
return Person.random(self)

@property
def zip_code(self) -> str:
return self.generator.postcode()
Loading

0 comments on commit 71ce6c5

Please sign in to comment.