Daniel's Weblog
Posts About
Tags Colophon

Tags / Pre2025

List Files in Directory with their Git Create Date

Extending ls to display the date each output file was created in a git repository.

The Command:

ls | xargs -t -I % git log --diff-filter=A -- % 2>&1 | grep "Date\|log"

Sample Output:

Produces a result like

git log --diff-filter=A -- 2018-10-31-sensor-hardware.md
Date:   Wed Oct 31 16:18:12 2018 -0400
git log --diff-filter=A -- 2018-11-05-Railroad-logos.md
Date:   Thu Nov 8 05:51:50 2018 +0000
git log --diff-filter=A -- 2018-11-09-ADSB-Guide.md
Date:   Thu Jan 24 15:00:06 2019 -0500

Breaking it down:

ls

List the files in the current directory

xargs

xargs reads items from the standard input, delimited by blanks (which can be protected with double or single quotes or a backslash) or newlines, and executes the command (default is /bin/echo) one or more times with any initial-arguments followed by items read from standard input. Blank lines on the standard input are ignored.

https://linux.die.net/man/1/xargs

xargs -t -I % git log --diff-filter=A -- % 2>&1
       |                |                   |-> Combine stderr and stdout
       |                |                       Needed because -t prints to stderr
       |                |            
       |                |-> Filter commits based on what happened to the file,
       |                    "A" means only display commits where the file
       |                    was added
       |                        
       |-> Print the command that will be executed to stderr before executing it
           (This is where grep extracts the filename)

diff-filter documentation. Other useful options include C for copied and R for renamed, these options can also be combined!

If we exclude 2>&1 and grep for a moment and just run ls | xargs -t -I % git log --diff-filter=A -- % this is what we see:

git log --diff-filter=A -- 2018-10-31-sensor-hardware.md
commit 1e273670ee661839e813c859007fda2cacb670d9
Author: djbeadle <████████@█████.com>
Date:   Wed Oct 31 16:18:12 2018 -0400

    Temp Sensor Part III
git log --diff-filter=A -- 2018-11-05-Railroad-logos.md
commit e25fb5135645a2f241a1bbea003f71c09126dc8a
Author: djbeadle <████████@█████.com>
Date:   Thu Nov 8 05:51:50 2018 +0000

    Made it a markdown file
git log --diff-filter=A -- 2018-11-09-ADSB-Guide.md
commit 5ece46b85b8b7fed20ccc3b67ced29d7e5aeb0f8
Author: djbeadle <████████@█████.com>
Date:   Thu Jan 24 15:00:06 2019 -0500

    Rename ADSB post, create new post on FlaskWTF and QuillJS

(Email censored by hand to make things a little harder on the bots)

This output is useful, but it’s a little more wordy than what we would like. Also it’s split in to stderr and stdout as follows:

STDERR: git log --diff-filter=A -- 2018-10-31-sensor-hardware.md
STDOUT: commit 1e273670ee661839e813c859007fda2cacb670d9
        Author: djbeadle <████████@█████.com>
        Date:   Wed Oct 31 16:18:12 2018 -0400

            Temp Sensor Part III

We can merge that with 2>&1| and send it to the next step

grep

Nothing fancy going on here, grep "Date\|log" searches for “Date” or “log” and exports lines that contain either of them.

This finally leaves us with the following:

git log --diff-filter=A -- 2018-10-31-sensor-hardware.md
Date:   Wed Oct 31 16:18:12 2018 -0400

Further Processing

We could do something fancy to parse our output in to CSV format, but since I only need to do this for one or two files right now I just copy and paste the output in to Notepad++ and use the super userful macro feature to wrangle the text in to the exact format I need. If you haven’t used Notepad++’s macro feature you’re missing out, find it under the Macro menu!

Implementing this in bash is left as an exercise to the reader. 😉


COVID-19 Signs on Instagram

It turns out that I wasn’t the only one who created an Instagram account for pictures of COVID-19 related signs.

My account is @covid_19_signs_nyc.

Other people have made accounts such as @covid19signslimerick, @duetocovid19, @signs_of_covid, and @signs_ofcovid. There’s even a website aggregating signs from multiple sources at duetocovid19.com.


PyCharm Quick Documentation Sphinx Support

A list of the Restructured Text Syntax and Sphinx roles that PyCharm supports in docstrings.

Be sure to set “Docstring format” to “reStructuredText” in setttings.

Function Parameters:

def do_the_thing(the_thing, another_thing=None):
    """
    :param int the_thing: The thing's primary key
    :param another_thing: A second thing to also do specified by an int or a string
    :type another_thing: Union(int, string)

    :returns: A string with the outpu text form running the thing
    :rtype: str
    """

PyCharm will reorder the params in the documentation based on the order of the params in the function definition.

:param TYPE PARAM_NAME: DESCRIPTION

is a syntactic sugar for

:param PARAM_NAME: DESCRIPTION
:type PARAM_NAME: TYPE

and is functionally equivalent. The only exception is that in the shortcut the type can only be a single word. There is no syntactic sugar for specifying the return type and description on the same line.

Notes:

  1. Multiple Supported Types

    :type PARAM_NAME: TYPE_ONE or TYPE_TWO
    :rtype: TYPE_ONE or TYPE_TWO
    

    Can be used to list multiple types for a single parameter or return value. PyCharm will render this as Union(TYPE_ONE, TYPE_TWO)

  2. List types

    List types can be specified by list[str].

Default Role

The default restructured text role `surrounded by backticks` has no meaning in restructured text and can be used for anything. It can be a nice way to indicate that you are referring to a python variable, method, or parameter. PyCharm will italicize any text surrounded by backticks.

Transitions

PyCharm will render a horizontal line based on any four or more repeated punctuation characters

Lists:

Bullet list

- This is a bullet list entry
- This is another bullet list entry
* Stars also work for bullet lists

Enumerated List

Enumerated lists do not work. The following:

1. This is an enumerated list item
2. This is another
#. This item should be auto enumerated with the number '3'

renders as follows:

. This is an enumerated list item
. This is another
. This item should be auto enumerated with the number '3'

Something is happening because item is placed on a new line, but it does not render as a numbered list

Definition List

doe
    A deer, a female deer
ray
    A drop of golden sun
me
    A name I call myself

will render properly.

Option List

Useful for listing command line arguments. Must be at least two spaces between the definition and the description.

-a           this flag sets the variable a
-b filename  sets the variable b to the provided filename
--input=other  this will also render correctly
/V           even DOS/VMS-style options will work
-c           long descriptions can be
             broken over multiple lines

Linking:

Sphinx defines several roles for the Python domain:

  1. :py:mod: for modules
  2. :py:func: for functions
  3. :py:data: for a module-level variable

The full list is available in the Sphinx docs

PyCharm supports a small selection with a slightly different syntax as listed below.

Linking to a class

:class:`SomeClassName`

This does not work inside of :param:, :type:, :return: descriptions.

Linking to an Exception

:exc:`SomeExceptionName`

This does not work inside of :param:, :type:, :return: descriptions.

Linking to a URL

http://someurl.com
`Link Name <http://someurl.com>`_

This does not work inside of :param:, :type:, :return: descriptions.

Math

Inline Math Formatting

PyCharm will italicize the following and make the powers into superscripts.

:math:`a^2 + b^2 = c^2

Other Semantic Markup

Sphinx has a selection of other miscellaneous roles documented here. The ones PyCharm supports in docstrings are listed below.

Linking to a PEP

:pep:`8`

Linking to an RFC

:rfc:`1462`

Other supported Restructured Text features

  1. Headers
  2. Sections
  3. Literal blocks
  4. Images

Restructured Text features that aren’t supported:

As of Dec 2019

  1. Line blocks
  2. Block quotes
  3. Doctest blocks
  4. Tables
    • They kind of work because of the headers, but they’re not great.
  5. Field lists
  6. Footnotes
    • PyCharm tries to make them into external links which fails.
  7. Sidebars
  8. Line Block

Notes on using Python Flask in 2019

Flask is a microframework for Python based on Werkzeug, Jinja 2 and good intentions.

Learning

Miguel Grinberg’s Flask Mega-Tutorial is the undisputable place to start and reference. I also strongly recommend his book, Flask Web Development. Be sure to get version 2.

Project Template

I maintain a reasonably well-documented skeleton of a Flask app built with the application factory and multiple configs.

Visual Studio Code

I don’t need to extole the virtues of VS Code.

Useful plugins:

Debugging:

Initial configuration:

  1. Enable the python interpreter by opening any Python file *.py. In the bottom left corner of the screen you should see which interpreter you’re using
  2. Switch to the debug module
  3. Select “Add Configuration” from the configuration dropdown
  4. Select “Flask” from the menu that appears
  5. Set the application path. If you’re using my project template the enterance file is myapp.py
  6. VSCode will now show you the file launch.json that it generated. If you want to set or change any environment variables you can do so here.

To run your code switch to the debug module and press the green arrow!

Bootstrap

Use Bootstrap-Flask, not Flask Bootstrap which hasn’t been updated since May, 2017 and doesn’t support Bootstrap 4.

The render_field() and render_form() macros are particurarly useful.

OpenID Connect (oidc)

I have had the most luck with Flask PYOIDC

Background tasks

RQ with Redis

Supervisord is an easy way to run the RQ workers. It’s written in Python2, but can run Python3 applications / scripts without any issues.

Deploying to Azure

Deploying a Flask app to Azure is remarkably easy–props to the team responsible for the wizardry that happens under the hood.

  1. Log in to <portal.azure.com>

  2. Select “Create a Resource” from the top left.

  3. Search for, select, and create a “Web App”.

  4. Fill in the web app details

    • Choose your subscription and resource group.
    • Give your application a name
    • Choose “Code” as your publish method
    • Choose the proper version of python for your runtime stack
    • Linux as your operating system
    • Choose the location most applicapable to you
  5. When the deployment is done open your new resource. The deployment process usually takes 20-30 seconds.

  6. Select the “Deployment Center” blade and the “Local Git” option.

  7. Select “App Service build service” and complete the process.

  8. The contents of the Deployment Center section has now changed. Azure has set up and empty git repository that we can push code to which it will build, host, and run. Copy the “Git Clone Uri” and add it to your local repository with the command

    git add remote [remote name] [remote uri]
    

    I like to call my deployment hosts “deploy” so for example:

    git add remote deploy https://daniel-flask.scm.azurewebsites.net:443/daniel-flask.git
    
  9. To actually deploy your code to this repository run:

    git push deploy master
    

    You will be prompted for a username and password which can be found by clicking on the key icon labled “Deployment Credentials” at the top of the Deployment Center.

  10. Almost done! If the startup file isn’t named “application.py” and/or isn’t located in the repository’s root folder Azure won’t find it. Open the “Configuration” blade and then to the “General Settings” tab. Fill in the “Startup Command” field as follows:

    gunicorn --bind=0.0.0.0 --timeout 600 [startup file minus extension]:[app object in that file]
    

    For example, using my my project template

    gunicorn --bind=0.0.0.0 --timeout 600 myapp:app
    

    You can find the full reference here

  11. To set environment variables navigate to the “Configuration” blade and add the “Application Settings” tab. You can reference them in your application with os.environ.get('Environment Variable Name')

  12. To restart your application to make the changes take effect navigate to the “Overview” blade and press the “Restart” button. Or push new code!

And that’s it! You can find the URL of you application on the “Overview” tab.


Pens, Pencils, and Paper Products in NYC

Need more pens, paper, and other writing products? Me neither, but I’m going to buy some anyways.

MUJI Fifth Avenue

My preferred Muji location is right across the street from Bryant Park and the New York Public Library (Which is also worth visiting either for books or to reenact Ghostbusters). They also have other locations throughout the city including Hudson Yards.

Google Maps describes Muji as “Minimalist Japanese retailer with a wide range of generic products, including apparel & home goods.” which is not technically wrong, but disregards their offerings of pens, mechanical pencils, and unbleached paper products (envelopes, pads of paper, sticky notes, etc.). None of their products are branded.

At their door is a table full of ink stamps where you can personalize your new notebook or an envelope you’re about to send to someone.

Of particular note are their following items:

  • Capped Gel Ink pens

    Wide range of covers, comfortable to hold and come in multiple sizes. Good for every day writing and note taking. Like most gel pens they will smudge on glossy surfaces, and not very water resistant. The pens can be bought individually or as a set.

  • Envelopes

    Okay, they’re really just envelopes. But they’re made out of kraft paper which makes them stand out and feel special.

  • Aluminum Round Fountain Pen

    This is probably the most expensive pen in the store, but it’s pretty inexpensive as fountain pens go. If you’re looking to dip your toes in the world of fountain pens this is a good way to start. Muji only sells black ink cartridges for this pen, but elsewhere you can buy convertors (like at Goods for the Study Mullberry detailed later) that allow you to refill it with whatever ink you like.

Stationary products are on the ground level, household goods, clothing, and more can be found in the basement. Muji products can also be ordered online on their website.

Casey Rubber Stamps

On East 11th Street between First and Second Avenues is a tiny store almost overflowing with rubber stamps. They’re more expensive than the stamps you’d find at your local craft store the broad selection is incredible. See something in the catalog that isn’t on the shelf? Wait 10 minutes and they’ll assemble it for you. Need custom stamps? They can do that too.

As the brochure says, “All of our equipment is state of the art circa 1955”. You can also order online from their website.

Kinokuniya New York

While Muji is restrained and spacious, Kinokuniya Books is doing their best to use every single square foot. On ground floor is a great collection of art, architecture, and design books. Upstairs is a Japanese cafe, manga, anime, and some western comic books too. In the basement is a huge collection of Japanese literature. I can’t read Japanese, but the way the series are color coordinated on the shelves is incredibly satisfying.

But we’re here to talk about pens, and a quarter of the basement is dedicated to pens, pencils, and decorative cards. Unlike Muji they don’t produce their own products, but if you need to restock your supply of Marvey LePen or pick up some more Blackwing pencils this store is conveniently located.

Goods for the Study Mullberry

Leaving midtown and heading south takes us to Goods for the Study Mulberry which is under the same ownership as McNally Jackson Books just around the corner. This store is split between two adjacent storefronts. On the right is notebooks, paperclips in the shape of animals, pen cases, paperweights, rulers, and more.

The store on the left is a more interactive experience. Jars of pens and mechanical pencils fill the walls and you’re invited to try them out. It’s a bit reminiscent of the Ollivander’s Wand Store in Harry Potter. If you’re searching for the perfect writing utensil this is the place to go.

Fountain pens and jars of ink are available here too. This in fact is where I bought a converter for my Muji fountain pen.

CW Pencil Enterprise

CW Pencil Enterprise takes a different approach from Goods for the Study. Instead of having many options, they have a small, carefully curated selection of pencils. If your idea of a writing utensil is a piece of wood with graphite in the middle, this is the place to visit.

Bowne Printers

Part of the Seaport museum, this is another store in two parts, Bowne and Co. Stationers has my favorite NYC-themed postcard designs. Right next door is Bowne Printers which is a 19th print shop selling cards and prints made there. They can also be commissioned for business cards and other prints.

Places I have not yet visited


Railway Logos and the Marching 97

There’s something magnetic about classic railway logos and graphics, they’re bright, they’re clean, they’re bold, and many have been around for decades!

Once upon a time Lehigh University’s unofficial mascot was the “Engineers”. There’s some debate whether this refers to the school’s engineering program or the Lehigh Valley Railroad which passed through Bethlehem and founder Asa Packer was heavily involved with.

Despite a 1995 decision to change the university mascot to the “Mountain Hawk” Lehigh’s band, the Marching 97, stands by the train engineer definition and still wears shirts with locomotives under their uniform.

I’ve made a couple railway-inspired logos for the band. As manager in fall of 2017 I gave out Union Pacific inspired pins at band camp (please don’t sue me, UP).

This year for Alumni Band Day (Nov. 8th) I was itching to make something– I hadn’t even opened up Photoshop since the yearbook was finished in August! Drawing inspiration from the Delaware and Hudson Railway, this graphic is probably more lawsuit-safe as the Lehigh Valley railroad was bought in 1976 (please don’t sue me, Conrail).

One other graphic I’ve been working on since before the 2018 London Trip is a riff on the Chicago NorthWestern logo. It won’t fit on a button as well as the other logos, but maybe it’ll exist as a sticker someday?

Notes

  • I keep an album on Flickr solely of railway graphics I come across. Many of these photos were taken at the Whippany Railroad Museum in Whippany, NJ, which has an excellent collection of exhibits and equipment! The uncredited photos in this post were taken there.
  • If you’re looking for more train-based graphic design inspiration, Reagan Ray has a wonderful collection of good, clean, scans of railway logos on his website.
  • Christian Annyas has written a fascinating blog post on the evolution of these graphics.

Self-Hosting Gitea

Since I graduated my student discount expired and I don’t want to pay $7 a month to Github for private repositories. So time to take Gitea for a whirl.

  1. Install from the binary
  2. Set up the service
    One minor change here, since I’m running Grafana on port 3000 already I’m going to run Gitea on port 4000 by doing modifying the following line:
ExecStart=/usr/local/bin/gitea web -p 4000 -c /etc/gitea/app.ini
  1. Add a proxy pass rule for Apache:
    /etc/apache2/sites-enabled/danielbeadle.net.conf
ProxyPass /git http://localhost:4000
  1. Set the root_url for Gitea /etc/gitea/app.ini
ROOT_URL = https://danielbeadle.net/git/
  1. Navigate to the install page https://danielbeadle.net/git/install
  • Database type: SQLite3
  • Path: /home/git/gitea/data/gitea.db
  • Repo Root Path: /home/git/gitea-repositories
  • Run as Username: git
  • ssh Server domain: danielbeadle.net

Update as of November, 2018: I have migrated all of my private repositories (including the one this website is tracked with) over to Gitea and it is working wonderfully. In was as simple as cloning my private repos from Github, initalizing a new repo in Gitea, changing the remote, and pushing.


Angular Recipes

Or: things I have implemented multiple times while developing in Angular 2 / Angular 6. Mostly for my own reference, but if it helsp someone else, great. This is a living post that I will add to and edit as I continue to develop in Angular without necessarily timestamping changes.

<a [routerLink]="['/interface-client']">All Clients</a> > <a [routerLink]="['/interface-client/', id]">{{ client.name }}</a>

Display Scrollbar while Bootstrap Modal is open

.modal-open
{
  overflow-y: scroll;
}

Source

Monitor how Bootstrap Modal was closed from parent

parent.component.ts

openModal() {
  const modalRef = this.modalService.open(ConfirmModalComponent); // Open modal
  modalRef.componentInstance.model = this.model; // Pass object to modal

  // Change the variable submitted based on how the modal was closed
  modalRef.result.then(value => { this.submitted = value === 'submitted' ? true : false; });
}

confirm-modal.component.ts:

onSubmit() {
  this.dataService.newApp(this.model);
  this.activeModal.close('submitted');
}

onCancel() {
  this.activeModal.close('canceled');
}

Dynamically Change Dropdown Contents (Angular Forms)

Say I have two dropdown elements in the form of select tags, one with id “species” and the other with id “name”. I want the available names to change based on the species currently selected, and I never want either dropdown to be blank.

More good advice: KastePanyan24 on Medium

Here is a working example on stackblitz.

app.component.html

<h3>INPUT:</h3>

<form *ngIf="formReady === true">
  <div class="form-group">
    <label for="species">Species: </label>
    <select class="form-control"
            id="species"
            (change)="onChange($event.target.value)"
            [(ngModel)]="model.species"
            name="f_species">
      <option *ngFor="let species_singular of species" [value]="species_singular">
        {{ species_singular }}
    </select>
  </div>

  <div class="form-group">
    <label for="name">Name: </label>
    <select class="form-control"
            id="name"
            [(ngModel)]="model.name"
            name="f_name">
      <option *ngFor="let name of appropriateNames" [value]="name.name">
        {{ name.name }}
    </select>
  </div>
</form>

<h3>OUTPUT:</h3>
<pre>{{ model.species }}, {{ model.name }}</pre>

app.component.ts

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
  /* The model the form begins with. */
  model = { species: 'cat', name: 'spot' }

  /* Our data */
  species: string[] = ['cat', 'dog'];
  names = [
    { species: 'cat', name: 'smokey' },
    { species: 'cat', name: 'spot' },
    { species: 'dog', name: 'kobe' },
    { species: 'dog', name: 'cheddar' }
  ];

  /* The names allowed to be used with the currently selected species */
  appropriateNames;

  /* Delay rendering of the form until appropriateName has been populated.
   * Without this the name dropdown is empty until the species is changed, which
   * is rather inconvenient if you want to use the first species in the dropdown */
  formReady: boolean = false; 

  ngOnInit()
  {
    /* Run the change event handler on page load to populate appropriateNames
     * variable and the name dropdown */
    this.onChange(this.model.species);
    this.formReady = true;
  }

  /**
   * Runs every time the species drop down is changed and populates
   * the name dropdown with the names available for that species.
   * 
   * @param species The species currently selected
   */
  onChange(species: string) {
    console.log('selected species: ', species);

    /* Everytime the dropdown changes the name array is iterated through. 
     * With large arrays this could slow things down, but I haven't had any 
     * issues with small arrays */
    this.appropriateNames= this.names.filter(obj => {
      return obj.species === species;
    });

    /* Change the name dropdown to the first item in the appropriateName array */
    this.model.name = this.appropriateNames[0].name;

    console.log(this.appropriateNames);
  }
}

Ng2-Smart-Table is a great library. Unfortunately, linking inside of a cell is a little difficult. I wanted to use [routerLink] inside the cell, but Angular kept sanitizing it.

To use [routerLink] inside of a cell, create a sub-component.

The table variables look like this:

// Table Stuff
private values = [];
source: LocalDataSource;
settings = {
  actions: {
    add: false,
    edit: false,
    delete: false
  },
  mode: 'external',
  columns:
  {
    tableData: {
      title: 'Hostname',
      type: 'custom',
      renderComponent: LinkComponent
    }
  }

And to populate the table data:

this.dataService.fetchHosts(key).subscribe((result: object[])  => {
  result.map(mapped => {
    const value = mapped['value'];
    this.values.push({ tableData: value });
  });
  this.source.load(this.values);
});

The subcomponent, LinkComponent looks like this:

export class HostnameCellComponent implements OnInit{
  @Input() value: string;

Pass multiple pieces of data in to a Ng2-Smart-Table sub-component

Okay, but what if your link needs multiple variables to generate it? Unfortunately, the easiest way I found to do this is to create a sub-component as above, concatenate your variables in to a single, comma seperated, string, pass said string in to the component, and split it up there.

This is gross, but it means the table is still sortable.

valuelink.component.ts:

export class HostnameCellComponent implements OnInit{
  @Input() value: string;
  value_part1: string = '';
  value_part2: string = '';

  constructor(private route: ActivatedRoute, private router: Router) {
  }

  ngOnInit()
  {
    const array: string[] = this.value.split(',');
    this.value_part1 = array[0];
    this.value_part2 = array[1];
  }
}

On/Off AC Control Systems

It’s gotten very warm the past few days… lets take a crack at adding some logic to my “dumb” window AC unit to keep things cool!

The Cooling System:

My in-window air conditioner is not particurarly fancy.

What it can’t do:

❌ Remote Control
❌ Automatic turn on / off
❌ Network connectivity
❌ Turn on at set time

What it can do:

✅ Put out cool air

And to its credit, it does do a decent job at that, but I want more!

Making it smarter!

I need to know is the current temperature in the room. I’m currently doing that with an Arduino, an ethernet shield, and an Si7021 temperature / humidity sensor. It sits on my cabinet on the other side of the room and when I punch in it’s IP address it responds with a bare-bones website displaying the current data

Once a minute it also pushes a reading to my local InfluxDB server (hosted on site on a Raspberry Pi) for record keeping. I’m using Grafana to make all fo these pretty graphs.

I’ve got another Raspberry Pi connected to a Powerswitch Tail 2. It queries the InfluxDB every 2 minutes or so to get the temperature in the room and turns on, or off, the AC accordingly.

{
  "fahrenheit": 72.65,
  "celsius": 22.58,
  "relative humidity": 40.62,
  "relative light level": 0
}

You can see the code running the Arduino Sensor and the Raspberry Pi


Water Measurements... from the Command Line

You know what I don’t have any practical use for? A command line tool to get USGS water data!

But, inspired by this Swiss tool I made one anyways.

Some USGS sensors don’t include water temperature, but they’ve got other cool stuff like discharge and gage height. With the power of hipsterplot, we can get some cool output!

Much more fun than writing essays, and it’s totally going in my /etc/profile file :-)

https://github.com/djbeadle/USGS-Water-CLI