Intro

Este notebook se podrá usar como plantilla para resolver los ejercicios PyBites de la plataforma codechalleng.es

Pre-requerimientos

  • Tener una licencia válida para poder acceder al ejercicio (Bite) completo.
  • Intalar chromium-chromedriver y configurarlo.
  • Instalar Selenium.

Uso

  • Establecer como variable de entorno del sistema global tu USERNAME y PASSWORD de la plataforma codechalleng.es (Celda #1)
  • Realizar el proceso de Login en la plataforma codechalleg.es ejecutando la (Celda #2)
  • Establecer el número del ejercicio (BITE_NUM) a resolver (Celda #3)
  • Mostrar el contenido del archivo PB_FILE utilizando el comando !cat (Celda #4)
  • Imprimir el nombre del archivo (BITE_NAME) (Celda #5)
  • Sobrescribir el archivo (BITE_NAME) con la solución utilizando el comando mágico de celda %%writefile (Celda #6)
  • Asegurarse de pasar las pruebas (PB_TEST) utilizando pytest (Celda #7)
  • Salvar la solución (CODE) y ejecutar las pruebas en la plataforma codechalleng.es (Celda #8)
  • Resolver otros ejercicios, repetir el proceso a partir de la* (Celda #3)**
# https://gist.github.com/korakot/5c8e21a5af63966d80a676af0ce15067
!apt install chromium-chromedriver
!pip install selenium

%env PB_USER=YOUR_USERNAME
%env PB_PW=YOUR_PASSWORD
# https://gist.github.com/pybites/0aa6d9833849a0942ed218b1d46c47b4#file-platform_login_selenium-py
import os
from IPython.display import HTML
# make venv and pip install selenium
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC


# Set your codechalleng.es username and password in venv/bin/activate, then source it
USERNAME = os.getenv("PB_USER") or "YOUR_USERNAME"
PASSWORD = os.getenv("PB_PW") or "YOUR_PASSWORD"

BASE_URL = "https://codechalleng.es"
LOGIN_URL = f"{BASE_URL}/login/"
WAIT_SECONDS = 2
CODE_TEMPLATE = ""
TEST_NAME = ""
CODE_TEST = ""


# Set options to be headless, ..
options = webdriver.ChromeOptions()
options.add_argument('--headless')
options.add_argument('--no-sandbox')
options.add_argument('--disable-dev-shm-usage')


# Open it, go to a website, and get results
driver = webdriver.Chrome('chromedriver', options=options)

driver.get(LOGIN_URL)
  
driver.find_element_by_name('username').send_keys(USERNAME)
driver.find_element_by_name('password').send_keys(PASSWORD + Keys.RETURN)
print("You are being logged")
  
You are being logged
# Set your Bite to code
BITE_NUM = 110

PYBITES_BITE_URL = f"{BASE_URL}/bites/{BITE_NUM}"
driver.get(PYBITES_BITE_URL)
# do your thing
#_html = driver.page_source
#print(_html)
contentWrapperElement = driver.find_element_by_css_selector("div.mui-col-md-8")
contentWrapperElement = contentWrapperElement.get_attribute("innerHTML")
# Implicit Wait
driver.implicitly_wait(WAIT_SECONDS)
element = driver.find_element_by_name("template_code")
CODE_TEMPLATE = element.get_attribute("value")
element = driver.find_element_by_xpath("//a[@data-mui-controls='pane-default-2']/span")
element.click()
TEST_NAME = element.text
TEST_NAME = TEST_NAME.strip("(").strip(")")
driver.execute_script("mui.tabs.activate('pane-default-2')")
# Simular Copy/Paste en Selenium
# Copy
cb = driver.execute_script("return copyTestToClipBoard();")
alert = driver.switch_to.alert
alert.accept()
driver.switch_to.default_content
# Crear textArea
js = """
function createTextArea(){
      var tArea = document.createElement('textarea');
      tArea.id = 'myTestCode';
      var pane = document.getElementById('pane-default-2');
      pane.appendChild(tArea);
}
createTextArea();
"""
cb = driver.execute_script(js)
# Paste
textAreaElement = driver.find_element_by_id("myTestCode")
textAreaElement.click()
textAreaElement.send_keys(Keys.CONTROL + "v")
CODE_TEST = textAreaElement.get_property("value")


BITE_NAME = TEST_NAME.split("test_")[1]

with open(BITE_NAME, "w") as file:
  file.write(CODE_TEMPLATE)
  os.environ["PB_FILE"] = BITE_NAME

with open(TEST_NAME, "w") as file:
  file.write(CODE_TEST)
  os.environ["PB_TEST"] = TEST_NAME

_html = contentWrapperElement + "\n\n" + \
f"<b>{BITE_NAME} and {TEST_NAME} files written to local storage!</b>"

HTML(_html)

GH avatar Bite 110. Type conversion and exception handling

In this Bite you complete the divide_numbers function that takes a numerator and a denominator (the number above and below the line respectively when doing a division).

First you try to convert them to ints, if that raises a ValueError you will re-raise it (using raise).

To keep things simple we can expect this function to be called with int/float/str types only (read the tests why ...)

Getting passed that exception (no early bail out, we're still in business) you try to divide numerator by denominator returning its result.

If denominator is 0 though, Python throws another exception. Figure out which one that is and catch it. In that case return 0.

division.py and test_division.py files written to local storage!
!cat $PB_FILE
def divide_numbers(numerator, denominator):
    """For this exercise you can assume numerator and denominator are of type
       int/str/float.
       Try to convert numerator and denominator to int types, if that raises a
       ValueError reraise it. Following do the division and return the result.
       However if denominator is 0 catch the corresponding exception Python
       throws (cannot divide by 0), and return 0"""
    pass

Copy and paste the Code Template into the next cell. Write the solution and overwrite it to the file using the magic command %%writefile \<PB_FILE> in the first line of the cell

print(f"%%writefile {BITE_NAME}")
%%writefile division.py
%%writefile division.py

def divide_numbers(numerator, denominator):
  try:
    numerator, denominator = int(numerator), int(denominator)
    result = numerator / denominator
  except ValueError as error:
    raise(error)
  except ZeroDivisionError as error:
    result = 0

  return result
Overwriting division.py

Uncomment the next line and run it until passing tests with pytest

#!pytest --capture=fd $PB_TEST
!python -m pytest $PB_TEST
print(f"!python -m pytest -V {TEST_NAME}")
============================= test session starts ==============================
platform linux -- Python 3.6.9, pytest-3.6.4, py-1.8.1, pluggy-0.7.1
rootdir: /content, inifile:
plugins: typeguard-2.7.1
collected 9 items                                                              

test_division.py .........                                               [100%]

=========================== 9 passed in 0.06 seconds ===========================
!python -m pytest -V test_division.py

When you are sure that your code passes the Test, execute the next cell for ”SAVE AND RUN TESTS

with open(BITE_NAME, "rb") as file:
  CODE = file.read()

CODE = str(CODE).strip("b").strip("'").strip('"')

js = f"""function MyCopyCodeToForm(){{
  var code = `{CODE}`;
  document.getElementById('code').value = code;
}}
MyCopyCodeToForm();
var saveRunTest = document.getElementById('save');
saveRunTest.setAttribute('onclick', 'return MyCopyCodeToForm();')
saveRunTest.click();
"""
driver.execute_script(js)
print("SAVE AND RUN TESTS")
SAVE AND RUN TESTS