Mariano Guerra: Creemos en la Web: Reusando estilo (de otros)

Introduccion

En las secciones anteriores aprendimos como reusar el estilo guardándolo en un archivo separado y cargándolo en múltiples paginas.

A medida que vamos creando mas y mas paginas empiezan a surgir cosas comunes que se usan en casi cualquier proyecto.

Si miras con atención las paginas que visitas vas a ver que hay ciertos componentes que se repiten.

De esto te podrás imaginar que con tanto reusar estilos y llevarlos de un proyecto a otro a alguien se le habrá ocurrido la idea de hacer un archivo de estilos lo suficientemente genérico para que pueda ser el estilo inicial de mucha gente que quiere crear una pagina web nueva pero no quiere estar definiendo de cero todo cada vez que empieza.

Imaginas bien!

Hay varios, pero el mas conocido se llama bootstrap, y nos permite empezar nuestras paginas sin tener que preocuparnos por detalles que al fin del día no son tan importantes.

Mas interesante, es que como este proyecto estandariza los nombres de clases para cada estilo, hay gente que crea nuevos estilos que se cargan "sobre" bootstrap y que le cambian el aspecto sin que nosotros tengamos que hacer nada mas que agregar una linea a nuestro HTML!

Podes ver algunos ejemplos en https://bootswatch.com/

Incluyendo Bootstrap

Vamos a ver como usar esto, empecemos con un proyecto nuevo en thimble con una pagina básica:

<!doctype html>
<html>
  <head>
        <meta chartset="utf-8">
        <title>Mi Pagina</title>
  </head>

  <body>
        <h1>Esto es un título</h1>

        <p>Esto es un párrafo, la siguiente palabra es en <b>negrita</b>, la siguiente en <i>itálica</i></p>

        <p>Esto es otro párrafo</p>

        <p>
          Una lista no ordenada:
        </p>

        <ul>
          <li>Manzana</li>
          <li>Durazno</li>
          <li>Banana</li>
        </ul>

        <p>Una lista ordenada:</p>

        <ol>
          <li>Uno</li>
          <li>Dos</li>
          <li>Tres</li>
        </ol>

        <p>Un link a <a href="https://google.com">Google</a></p>

  </body>
</html>

Nuestra pagina de siempre, no muy linda de ver:

/galleries/cew/6/01-base.png

Ahora agregamos la hoja de estilo de bootstrap en el <head> de la pagina, debajo del tag <title>:

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css">

Y podemos ver que ya cambio un poco:

/galleries/cew/6/02-base-bootstrap.png

Un tour por algunos componentes de bootstrap

Pero si fuera solo por eso entonces no seria tan útil, esto es solo el contenido base, bootstrap nos provee con muchos componentes estandard para usar, empecemos por las alertas:

Alertas

Agreguemos el siguiente HTML al <body> de nuestro proyecto:

<h2>Alertas</h2>

<div class="alert alert-primary" role="alert">
  Alerta principal (primary)
</div>
<div class="alert alert-secondary" role="alert">
  Alerta secundario (secondary)
</div>
<div class="alert alert-success" role="alert">
  Alerta exito (success)
</div>
<div class="alert alert-danger" role="alert">
  Alerta peligro (danger)
</div>
<div class="alert alert-warning" role="alert">
  Alerta advertencia (warning)
</div>
<div class="alert alert-info" role="alert">
  Alerta informacion (info)
</div>
<div class="alert alert-light" role="alert">
  Alerta claro (light)
</div>
<div class="alert alert-dark" role="alert">
  Alerta oscuro (dark)
</div>

<h2>Alertas con mas contenido</h2>

<div class="alert alert-info" role="alert">
  <h4 class="alert-heading">Titulo</h4>
  <p>Contenido principal.</p>
  <hr>
  <p class="mb-0">Contenido despues del separador.</p>
</div>

Debería verse algo así:

/galleries/cew/6/03-bs-alerts.png

Badges

Badges se traduce a medalla o distintivo, es mas fácil entender que son viéndolos que por la palabra, así que agreguemos el siguiente HTML a nuestra pagina:

<h2>Badges</h2>

<h3>Estandar</h3>

<div class="m-3">
  <span class="badge badge-primary">Principal</span>
  <span class="badge badge-secondary">Secundario</span>
  <span class="badge badge-success">Exito</span>
  <span class="badge badge-danger">Peligro</span>
  <span class="badge badge-warning">Advertencia</span>
  <span class="badge badge-info">Informacion</span>
  <span class="badge badge-light">Claro</span>
  <span class="badge badge-dark">Oscuro</span>
</div>

<h3>Pill Badges (Pastillas)</h3>

<div class="m-3">
  <span class="badge badge-pill badge-primary">Principal</span>
  <span class="badge badge-pill badge-secondary">Secundario</span>
  <span class="badge badge-pill badge-success">Exito</span>
  <span class="badge badge-pill badge-danger">Peligro</span>
  <span class="badge badge-pill badge-warning">Advertencia</span>
  <span class="badge badge-pill badge-info">Informacion</span>
  <span class="badge badge-pill badge-light">Claro</span>
  <span class="badge badge-pill badge-dark">Oscuro</span>
</div>

<h3>Links</h3>

<div class="m-3">
  <a href="#" class="badge badge-primary">Principal</a>
  <a href="#" class="badge badge-secondary">Secundario</a>
  <a href="#" class="badge badge-success">Exito</a>
  <a href="#" class="badge badge-danger">Peligro</a>
  <a href="#" class="badge badge-warning">Advertencia</a>
  <a href="#" class="badge badge-info">Informacion</a>
  <a href="#" class="badge badge-light">Claro</a>
  <a href="#" class="badge badge-dark">Oscuro</a>
</div>

Como veras rodeo los ejemplos con un div para darle mas margen, pero no uso style="margin: ..." como hasta acá, sino que uso una clase que bootstrap provee que estandariza los margenes en 6 niveles (m-0, m-1, ..., m-5). De esta manera si usamos estas clases en nuestras paginas los margenes serán consistentes y luego podremos ajustarlos en un solo lugar (la definición de .m-0, ..., .m-5 en nuestra hoja de estilos)

El resultado es algo así:

/galleries/cew/6/04-badges.png

Barra de Navegacion

Otro componente muy útil y versátil son las barras de navegación, suelen usarse en la parte superior de la pagina y en cualquier sección que tiene mas de un elemento para mostrar, como los tabs del navegador web.

<h2>Barra de Navegacion</h2>

<h3>Usando tags de lista</h3>

<ul class="nav">
  <li class="nav-item">
    <a class="nav-link active" href="#">Activo</a>
  </li>
  <li class="nav-item">
    <a class="nav-link" href="#">Link</a>
  </li>
  <li class="nav-item">
    <a class="nav-link" href="#">Link</a>
  </li>
  <li class="nav-item">
    <a class="nav-link disabled" href="#">Inactivo</a>
  </li>
</ul>

<h3>Usando el tag nav</h3>

<nav class="nav">
  <a class="nav-link active" href="#">Activo</a>
  <a class="nav-link" href="#">Link</a>
  <a class="nav-link" href="#">Link</a>
  <a class="nav-link disabled" href="#">Inactivo</a>
</nav>

<h3>Justificado al centro</h3>

<nav class="nav justify-content-center">
  <a class="nav-link active" href="#">Activo</a>
  <a class="nav-link" href="#">Link</a>
  <a class="nav-link" href="#">Link</a>
  <a class="nav-link disabled" href="#">Inactivo</a>
</nav>

<h3>Justificado a la derecha</h3>

<nav class="nav justify-content-end">
  <a class="nav-link active" href="#">Activo</a>
  <a class="nav-link" href="#">Link</a>
  <a class="nav-link" href="#">Link</a>
  <a class="nav-link disabled" href="#">Inactivo</a>
</nav>

<h3>Tabs</h3>

<nav class="nav nav-tabs">
  <a class="nav-link active" href="#">Activo</a>
  <a class="nav-link" href="#">Link</a>
  <a class="nav-link" href="#">Link</a>
  <a class="nav-link disabled" href="#">Inactivo</a>
</nav>

<h3>Pills</h3>

<nav class="nav nav-pills">
  <a class="nav-link active" href="#">Activo</a>
  <a class="nav-link" href="#">Link</a>
  <a class="nav-link" href="#">Link</a>
  <a class="nav-link disabled" href="#">Inactivo</a>
</nav>

<h3>Tabs Expandidas (Lista)</h3>

<ul class="nav nav-tabs nav-fill">
  <li class="nav-item">
    <a class="nav-link active" href="#">Activo</a>
  </li>
  <li class="nav-item">
    <a class="nav-link" href="#">Link</a>
  </li>
  <li class="nav-item">
    <a class="nav-link" href="#">Link</a>
  </li>
  <li class="nav-item">
    <a class="nav-link disabled" href="#">Inactivo</a>
  </li>
</ul>

<h3>Pills Expandidas (Nav)</h3>

<nav class="nav nav-pills nav-fill">
  <a class="nav-item nav-link active" href="#">Activo</a>
  <a class="nav-item nav-link" href="#">Link</a>
  <a class="nav-item nav-link" href="#">Link</a>
  <a class="nav-item nav-link disabled" href="#">Inactivo</a>
</nav>

El resultado es algo así:

/galleries/cew/6/05-nav.png

Luego de explorar los componentes copiando y pegando los ejemplos intenta modificarlos, agregar mas items, eliminar algunos, reordenarlos etc.

Si te sentís aventurero, intenta mirar un ejemplo y luego tiperarlo por completo solo mirando el ejemplo cuando te olvides de algo o algo no funcione.

Este ejercicio es una buena forma de memorizar los conceptos básicos y de ver cuales partes pensabas que entendías pero todavía algún detalle se escapa.

Roberto Alsina: Código Charla PyDay "Como Hacer una API REST en Python, spec first"

El 4/4/2018 di una charla en un PyDay sobre como implementar una API REST a partir de una especificación hecha en Swagger/OpenAPI usando Connexion

/images/pyday-api-rest.jpg

Foto tomada por Yamila Cuestas

Si bien no pude grabar la charla (alguien en la audiencia si lo hizo, pero no me dio el video! Pasame el video, persona de la audiencia!) y no hay slides, acá está el código que mostré, que es relativamente sencillo y fácil de seguir.

Código de la charla

Cualquier cosa pregunten.

PD: Sí, podría hacer la charla en un video nuevo. Sí, me da mucha pereza.

Roberto Alsina: My Git tutorial for people who don't know Git

As part of a book project aimed at almost-beginning programmers I have written what may as well pass as the first part of a Git tutorial. It's totally standalone, so it may be interesting outside the context of the book.

It's aimed at people who, of course, don't know Git and could use it as a local version control system. In the next chapter (being written) I cover things like remotes and push/pull.

So, if you want to read it: Git tutorial for people who don't know git (part I)

PS: If the diagrams are all black and white, reload the page. Yes, it's a JS issue. Yes, I know how to fix it.

Roberto Alsina: I have written half a book

LIke mentioned before I am trying to write a book and ... well, I may be actually making progress? At least the generated PDF is about 170 pages long, which means I have written a bunch in this past month.

I have finished the second of four planned parts, which means I have done about half of it. Since I expect the next two parts to be shorter, it's actually more than that.

The target audience are people who have finished the python tutorial but are not exactly programmers yet. They have the syntax more or less in their heads, but how do you turn that into an actual piece of code?

  • Part 1 is about "prototyping", the process of dumping an idea into rough code.
  • Part 2 is about polishing that rough code into ... not so rough code. Includes a gentle introduction to testing, for example.
  • Part 3 (to be written) is about things that are not code:
    • Git / Gitlab
    • Issues
    • Packaging
    • Setting up a website
    • CI
    • Lots more
  • Part 4 is still to be thought but basically it will cover implementing a large feature from the ground up.

I much appreciate comments about it.

PD: Si, va a haber una traducciń al castellano. O mas bien al argentino. Una vez que lo termine.

Joaquin Tita: Prevent ssh timeouts

Locally add the following to ~/.ssh/config
ServerAliveInterval 120 # null packet every 120 seconds
On the server side add the following:
ClientAliveInterval 120 # null packet every 120 seconds
ClientAliveCountMax 720 # 24hs

Done!

Joaquin Tita: fail2ban unban ip

To search all the ips that were banned we enter interactive mode:

$ fail2ban-client -i
Then we check a jail status, for example sshd:
> status sshd
the output:
Status for the jail: sshd
|- Filter
|  |- Currently failed: 0
|  |- Total failed: 27
|  `- File list: /var/log/auth.log
`- Actions
   |- Currently banned: 37
   |- Total banned: 38
   `- Banned IP list: <a big list of banned ips>

So, if we want to unban a particular ip address, let's say X
Then, we execute:
> set ssh unbanip (within interactive mode)

Lastly, if you want to execute it directly from command line:

$ fail2ban-client get <JAIL> actionunban <IP-ADDRESS>

That's all.

Facundo Batista: Actualización y nuevo proyecto


fades

Después de casi un año, con Nico liberamos una nueva versión de fades.

¿Qué hay de nuevo en esta release?

  • Revisar si todo lo pedido está realmente disponible en PyPI antes de comenzar a instalarlo
  • Ignora dependencias duplicadas
  • Varias mejoras y correcciones en los mensajes que fades muestra en modo verbose
  • Prohibimos el mal uso de fades: instalarlo en legacy Python y ejecutarlo desde adentro de otro virtualenv
  • Un montón de mejoras relacionadas al proyecto en sí (pero no directamente visibles para el usuario final) y algunas pequeñas otras correcciones

Pruébenlo.

Loguito de fades

infoauth

infoauth es un un pequeño pero práctico módulo de Python y script para grabar/cargar tokens a/desde disco.

Esto es lo que hace:

  • graba tokens en un archivo en disco, pickleado y zippeado
  • cambia el archivo a sólo lectura, y sólo legible por vos
  • carga los tokens de ese archivo en disco

En qué casos este módulo es útil? Digamos que tenés un script o programa que necesita algunos tokens secretos (autenticación de mail, tokens de Twitter, la info para conectarse a una base de datos, etc...), pero no querés incluir estos tokens en el código, porque el mismo es público, entonces con este módulo harías:

    tokens = infoauth.load(os.path.expanduser("~/.my-tokens"))

Fijate que el archivo va a quedar legible sólo por vos y no en el directorio del proyecto (así no tenés el riesgo de compartirlo por accidente).

CUIDADO: infoauth NO protege tus secretos con una clave o algo así, este módulo NO asegura tus secretos de ninguna manera. Sí, los tokens están enmarañados (porque se picklean y comprimen) y otra gente quizás no pueda accederlos fácilmente (legible sólo por vos), pero no hay más protección que esa. Usalo bajo tu propio riesgo.

Entonces, ¿cómo usarlo desde un programa en Python? Es fácil, para cargar la data:

    import infoauth
    auth = infoauth.load(os.path.expanduser("~/.my-mail-auth"))
    # ...
    mail.auth(auth['user'], auth['password'])

Para grabarla:

    import infoauth
    secrets = {'some-stuff': 'foo', 'code': 67}
    infoauth.dump(secrets, os.path.expanduser("~/.secrets"))

Fijate que como grabar los tokens es algo que normalmente se hace una sola vez, seguro es más práctico hacerlo desde la linea de comandos, como se muestra a continuación...

Por eso, ¿cómo usarlo desde la linea de comandos? Para mostrar la info:

    $ infoauth show ~/.my-mail-auth
    password: ...
    user: ...

Y para grabar un archivo con los datos::

    $ infoauth create ~/.secrets some-stuff=foo code=67

Fijate que al crear el archivo desde la linea de comandos tenemos la limitación de que todos los valores almacenados van a ser cadenas de texto; si querés grabar otros tipos de datos, como enteros, listas, o lo que quieras, tendrías que usar la forma programática que se muestra arriba.

Esta es la página del proyecto, y claro que está en PyPI así que se puede usar sin problema desde fades (guiño, guiño).