How to Setup a New Flask App on a Mac

This blog post is brought to you by the developer of BitBudget. BitBudget is an automated budgeting app for Android and iOS which syncs with your bank account and helps you avoid overspending. If you’d like to quit living paycheck-to-paycheck and get a better handle on your finances, download it today! https://bitbudget.io

Welcome back internet friend!

Quick post here tonight on how to setup a new flask app for development on a Mac. In the past I’ve done all of my Python/Flask development on a Windows desktop computer, but since I’m now doing all of my development on a Macbook Pro, I wanted to write another little quickstart reference for myself or anyone else out there on the internet to get up and running with Python and Flask on a Mac (assumes you’ve already installed Python 3, if you haven’t, please visit https://python.org):

First, create a directory for your new Flask project

$ mkdir MyNewFlaskApp

Navigate to your newly created directory

$ cd MyNewFlaskApp

Create your virtual environment

$ python3 -m venv venv

Activate the virtual environment

$ source venv/bin/activate

Make sure Flask is installed

(venv) $ pip3 install Flask

Now write the actual python code for your flask application. We’ll call our python script my_new_flask_app.py. Save this script in your MyNewFlaskApp directory.

from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return 'hello, world'

Set the FLASK_APP system variable

(venv) $ export FLASK_APP=my_new_flask_app.py

Run Flask

(venv) $ flask run

Visit http://127.0.0.1:5000 to see your app in action

 

Learn Golang in ~30 Minutes

This blog post is brought to you by the developer of BitBudget. BitBudget is an automated budgeting app for Android and iOS which syncs with your bank account and helps you avoid overspending. If you’d like to quit living paycheck-to-paycheck and get a better handle on your finances, download it today! https://bitbudget.io

I’ve been working with a student of mine recently in Golang and noticed that my skills were sort of lacking! So here’s a quick little cheat sheet reference for coding in Golang. If you need any help getting your computer setup to run Golang, check out Learn Go in 12 Minutes on YouTube.

If you haven’t already installed Golang and set up your environment, do that first…

Step 1: Install Golang

Then, create your “go” directory where you will store all of your golang projects on your local machine:

$ cd $HOME

$ mkdir go

$ cd go

$ mkdir src

$ cd src

Next, create a subdirectory for your project:

$ mkdir hello

$ cd hello

Now create a file called hello.go which will contain our hello, world program:

package main

import "fmt"

func main() {
	fmt.Printf("hello, golang\n")
}

Compile & Run:

$ go build

$ ./hello

Last, check out the example below (based on Learn Golang in 12 Minutes) as a reference/cheatsheet:

// REFERENCE (Learn Golang in 12 Minutes): https://www.youtube.com/watch?v=C8LgvuEBraI
package main
import (
"fmt"
)
func main() {
// functions
fmt.Println("hello, golang!")
// variables
var x int = 4
y := 7 // use walrus tooth operator to infer type
// if statements
if (x == 5) {
fmt.Println("x equals five!")
} else if (x != 5 && y == 7) {
fmt.Println("x does not equal five, but y equals seven...")
} else {
fmt.Println("I dunno man?")
}
// arrays (fixed length)
var a [5]int
a[0] = 100
a[1] = 101
a[2] = 102
a[3] = 103
a[4] = 104
fmt.Println(a[0])
// slices (adjustable length "array")
var b []int
b = append(b, 200)
b = append(b, 201)
b = append(b, 202)
b = append(b, 203)
b = append(b, 204)
fmt.Println(b[0])
// maps (key value pairs, "dictionary")
c := make(map[string]int)
c["foo"] = 300
c["bar"] = 301
c["baz"] = 302
fmt.Println(c["foo"])
// loops
// (no while loops in golang, only for loops!)
for i:= 0; i < 5; i++ {
fmt.Println(i)
}
// if you need something like a while loop,
// this can be accomplished with a for loop
// like so...
j := 0
for j < 1 {
fmt.Println("look at me go!")
fmt.Println("just kidding... lets shut it down!")
j = 1
}
}
view raw learngo.go hosted with ❤ by GitHub

Need to work with command line user input? Another cheatsheet:

// Command Line User Input in Golang
// REFERENCE: https://stackoverflow.com/questions/20895552/how-to-read-from-standard-input-in-the-console
package main
import (
"fmt"
"bufio"
"os"
)
func main() {
reader := bufio.NewReader(os.Stdin)
fmt.Print(">>> ")
userInput, _ := reader.ReadString('\n')
fmt.Println(userInput)
fmt.Print(">>> ")
userInput2, _ := reader.ReadString('\n')
fmt.Println(userInput2)
fmt.Print(">>> ")
userInput3, _ := reader.ReadString('\n')
fmt.Println(userInput3)
}
view raw userinput.go hosted with ❤ by GitHub

Need to ping a JSON API? More cheatsheet goodness from the folks at RapidAPI:

package main
import (
"fmt"
"net/http"
"io/ioutil"
)
func main() {
url := "https://community-hacker-news-v1.p.rapidapi.com/item/8863.json?print=pretty"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("x-rapidapi-host", "community-hacker-news-v1.p.rapidapi.com")
req.Header.Add("x-rapidapi-key", "472e13f6d7msh84492a2444096d4p1edbffjsn3ff4c1075778")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := ioutil.ReadAll(res.Body)
fmt.Println(res)
fmt.Println(string(body))
}

What about functions? See below:

package main
import(
"fmt"
)
func main() {
var favoriteNumbers []float64
favoriteNumbers = append(favoriteNumbers, 13.0)
favoriteNumbers = append(favoriteNumbers, 27.0)
favoriteNumbers = append(favoriteNumbers, 56.0)
favoriteNumbers = append(favoriteNumbers, 3.0)
favoriteNumbers = append(favoriteNumbers, 99.0)
favoriteNumbers = append(favoriteNumbers, 15.0)
averageFavoriteNumber := average(favoriteNumbers)
// REFERENCE (String Formatting): https://gobyexample.com/string-formatting
fmt.Printf("Average Favorite Number: %v", averageFavoriteNumber)
}
func average(numbers []float64) float64 {
var sum float64 = 0
for i := 0; i < len(numbers); i++ {
sum += numbers[i]
}
mean := sum / float64(len(numbers))
return mean
}
view raw funkyfunc.go hosted with ❤ by GitHub

Structs…

package main
import(
"fmt"
)
func main() {
fmt.Println("It's time to learn about Structs...")
chris := Person{FirstName: "Christopher", LastName: "Pedersen", Age: 33, Height: 68, Sex: "male"}
fmt.Println("Our first struct is a Person")
fmt.Printf("Our Person's first name is: %s \n", chris.FirstName)
fmt.Printf("Last name is: %s \n", chris.LastName)
fmt.Printf("Age: %d \n", chris.Age)
fmt.Printf("Height (in inches): %d \n", chris.Height)
fmt.Printf("Sex: %s", chris.Sex)
}
type Person struct {
FirstName string
LastName string
Age int
Height int
Sex string
}
view raw mystruct.go hosted with ❤ by GitHub

Confused about the need for Interfaces? See this explanation by Andy Joiner on Stack Overflow: Why are interfaces needed in Golang?

 

Auth0: Do users need to signup? Or can they just log in?

This blog post is brought to you by the developer of BitBudget. BitBudget is an automated budgeting app for Android and iOS which syncs with your bank account and helps you avoid overspending. If you’d like to quit living paycheck-to-paycheck and get a better handle on your finances, download it today! https://bitbudget.io

Tonight using Auth0 I started integrating social login with Google, Facebook, and Twitter into the latest development version of my personal finance app, Moolabeast, and found myself wondering: Do users need to signup? Or can they just log in?

While testing this new integration it appears there is no difference between signing up and logging in using a social media account. However, I really wanted to make sure that I get this right so I decided to dig a little deeper into the issue. Long story short: there is no difference between signing up and logging in. If a user clicks on “log in” instead of “sign up”, the end result is the same. Apparently Auth0 has just stuck with this old signup/login paradigm as it’s what internet users are used to. First I sign up, then I log in.

So I hope this clears up some confusion if you happen to be integrating social login with Auth0 into your app. Happy hacking my friend!

 

The 100 Year Historic Decline of Dividend Payout Ratios Amongst S&P 500 Companies

This blog post is brought to you by the developer of BitBudget. BitBudget is an automated budgeting app for Android and iOS which syncs with your bank account and helps you avoid overspending. If you’d like to quit living paycheck-to-paycheck and get a better handle on your finances, download it today! https://bitbudget.io

Welcome back internet friends!

This is actually a cross-post of a comment I posted recently to Hacker News. Unsurprisingly, the comment received negative 1 upvotes. However, I think this is an import piece of information that has gone missing from the World Wide Web, so I wanted to bring it back: The 100 Year Historic Decline of Dividend Payout Ratios for S&P 500 Companies

The hacker news thread on which I commented was regarding a recent headline on increasing S&P 500 Buybacks, but what I think is more troubling is the decline in dividend payout ratios, not the increase in buybacks. But the two are closely related, so let’s take a look:

100 years ago, companies on average dispersed 90% of their earnings back to shareholders as dividends. But by the 1970’s however that number fell to below 50%. Fast forward to the 2000’s and the payout ratio is down to around ~30%.

What happened? Companies used to distribute their profits back to their owners, the shareholders. But that isn’t what’s happening anymore. In my amateur historical analysis, I believe there are two causes for this disastrous trend:

1) Tax dodging
2) The Casino/Gambling Mentality of Stock Market Investing

My theory is that the trend started with investors 50 to 100 years ago looking to dodge taxes, and gain a little free compounding. Makes sense! Right?

But it’s just gone too far. Now investors receive almost nothing for owning a stock. Take Apple Inc. for example. In 2019 Apple made a profit of $55 billion. How much of that did they pay back to their shareholders? $14 billion.

And Apple isn’t even the most egregious case. They at least pay a dividend. Google, Amazon, and Facebook combined paid $0 back to their shareholders this year!


So how has this insanity continued to go on for so long? The answer is simple: Adults don’t know what stocks are. They think that a stock is a thing that you buy, its price goes up and down, and the game is to try and sell the stock when the price goes up, and hope that the price doesn’t go down. And the machine that keeps the whole thing moving along is the Stock Buyback.

REFERENCE: The Dividend Story

 

How do you debug a realm database that’s on a physical device?

This blog post is brought to you by the developer of BitBudget. BitBudget is an automated budgeting app for Android and iOS which syncs with your bank account and helps you avoid overspending. If you’d like to quit living paycheck-to-paycheck and get a better handle on your finances, download it today! https://bitbudget.io

Alright, so let’s get to it: How to debug a realm database running on a physical device:

Unfortunately, you cannot debug a realm database running on a physical device if it is already in production.

Hopefully this saves someone out there a ton of heartache, but after you have pushed your app out in to production, you can’t just open up a .realm file from your device using Realm Studio due to security restrictions. So if you happen to find yourself struggling to open a realm database that’s running on your personal device, and can’t seem to access the .realm file to debug it, it could be that your device isn’t allowing access to the file because it is a production app and is not debuggable via USB and Android Studio, etc.

Now, if you need to debug a development version of your app, it’s a different story. You can simply open up your app in Android Studio, with your physical device plugged into your computer, and open up the Device File Explorer in Android Studio, where you will be able to locate your .realm database file. From the Device File Explorer you can right-click and save the .realm file onto your computer and open it using Realm Studio.

If you need to be able to debug and inspect Realm database instances running on live production versions of your app, this may be possible with Realm’s new Realm Cloud product. However, I haven’t checked out Realm Cloud and Realm Sync just yet as I’m still getting my feet wet with Realm DB.

 

How to use ON DUPLICATE KEY UPDATE with Python, MySQL, and mysql.connector

This blog post is brought to you by the developer of BitBudget. BitBudget is an automated budgeting app for Android and iOS which syncs with your bank account and helps you avoid overspending. If you’d like to quit living paycheck-to-paycheck and get a better handle on your finances, download it today! https://bitbudget.io

Fret not distressed developer! Using the ON DUPLICATE KEY UPDATE feature of SQL with Python, MySQL, and mysql.connector can be a bit of a doozy once you add in parameterizing your queries. This personally took me quite awhile to figure out since most of the SQL references regarding ON DUPLICATE KEY UPDATE do not include the Python/mysql.connector specific aspects, and most of the Python/mysq.connector references do not mention ON DUPLICATE KEY UPDATE.

So here is the trick, you won’t be passing the SQL query values like usual with %s for the UPDATE part of your query. Instead you will write something like VALUES(name_column). For reference, here is a little snippet of code from one of my projects which should guide you in the right direction:

import mysql.connector
# Create MySQL Database Connection
database_connection = mysql.connector.connect(
host="99.111.11.99", # dummy ip address
user="your-super-sweet-admin-name",
passwd="y0uRpAsSw0Rd",
database="your_db"
)
cursor = database_connection.cursor()
values = (
"myTransactionID",
"myUserID",
"myName",
9.99,
"myCategoryA",
"myCategoryB",
"myCategoryC",
123,
"1970-01-01",
"XYZ",
"myAddress",
50.0,
50.0,
"CA",
"90210",
1,
"myTransactionType") # single tuple will hold one row worth of database data
sql = "\
INSERT INTO transaction_table \
(transaction_id_column, \
user_id_column, \
name_column, \
amount_column, \
category_a_column, \
category_b_column, \
category_c_column, \
category_id_column, \
date_column, \
iso_currency_code_column, \
address_column, \
lat_column, \
lon_column, \
state_column, \
zip_column, \
pending_column, \
transaction_type_column) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) \
ON DUPLICATE KEY UPDATE \
user_id_column = VALUES(user_id_column), \
name_column = VALUES(name_column), \
amount_column = VALUES(amount_column), \
category_a_column = VALUES(category_a_column), \
category_b_column = VALUES(category_b_column), \
category_c_column = VALUES(category_c_column), \
category_id_column = VALUES(category_id_column), \
date_column = VALUES(date_column), \
iso_currency_code_column = VALUES(iso_currency_code_column), \
address_column = VALUES(address_column), \
lat_column = VALUES(lat_column), \
lon_column = VALUES(lon_column), \
state_column = VALUES(state_column), \
zip_column = VALUES(zip_column), \
pending_column = VALUES(pending_column), \
transaction_type_column = VALUES(transaction_type_column)"
cursor.execute(sql, values)
database_connection.commit()
 

How to Programmatically Submit Websites & Webpages to the Internet Archive’s Wayback Machine

This blog post is brought to you by the developer of BitBudget. BitBudget is an automated budgeting app for Android and iOS which syncs with your bank account and helps you avoid overspending. If you’d like to quit living paycheck-to-paycheck and get a better handle on your finances, download it today! https://bitbudget.io

Welcome back internet friend,

Tonight I started hacking on an old project on which I’m currently bringing back to life, a chrome extension which saves all of the pages you visit to the Internet Archive’s Wayback Machine. It’s called The Internet Archivist’s Intrepid Extension.

Unfortunately I had to kill off the first version of the extension because cloudflare started blocking all of my traffic. However, I discovered today that Archive.org has an API for submitting links programmatically. So the Intrepid Extension is back!

After an hour or so of hacking I’ve put together a pretty simple prototype and thought maybe I should share the source code here on the blog in case anyone else is stumbling around the internet looking for a solution. Enjoy!

<!DOCTYPE html>
<html>
<body>
<input id="urlInput" type="text" size="40" placeholder="Enter URL to Archive">
<button onclick="archive();">ARCHIVE</button>
<script>
var data;
function archive() {
var urlInput = document.getElementById('urlInput');
var url = document.getElementById('urlInput').value;
urlInput.value = ""; // clear url text input field
ajaxRequest = new XMLHttpRequest();
if (!ajaxRequest) {
alert("ERROR 0001: PC LOAD LETTER");
return; // kill, do not run rest of function
}
// json data which we will be sending to the server via ajax
data = {
"url": url
};
ajaxRequest.onreadystatechange = function() {
if (ajaxRequest.readyState === XMLHttpRequest.DONE) {
if (ajaxRequest.status === 200) {
// raw server response, may need to parse JSON if
// the server you are pinging will be responding
// with JSON
var serverResponse = ajaxRequest.responseText;
console.log(serverResponse);
alert(serverResponse);
} else {
alert("ERROR 0002: PC LOAD LETTER ");
}
}
};
ajaxRequest.open('POST', "https://pragma.archivelab.org");
ajaxRequest.setRequestHeader('Content-type', 'application/json');
ajaxRequest.send(JSON.stringify(data));
}
</script>
</body>
</html>
 

FatCamp Privacy Policy

Privacy Policy

Your privacy is important to me. It is  my (Christopher Pedersen) policy to respect your privacy regarding any information I may collect from you on my app, FatCamp.


I only ask for personal information when we truly need it to provide a service to you. I collect it by fair and lawful means, with your knowledge and consent. I also let you know why I am collecting it and how it will be used.


I only retain collected information for as long as necessary to provide you with your requested service. What data I store, I will protect within commercially acceptable means to prevent loss and theft, as well as unauthorized access, disclosure, copying, use or modification.
I don’t share any personally identifying information publicly or with third-parties, except when required to by law.


My app may link to external sites that I do not operate. Please be aware that I have no control over the content and practices of these sites, and cannot accept responsibility or liability for their respective privacy policies.


You are free to refuse our request for your personal information, with the understanding that I may be unable to provide you with some of your desired services.


Your continued use of my website will be regarded as acceptance of our practices around privacy and personal information. If you have any questions about how I handle user data and personal information, feel free to contact me (chris@topherpedersen.com).


This policy is effective as of 4 December 2019.

 

TODO List in VanillaJS (for teaching purposes)

This blog post is brought to you by the developer of BitBudget. BitBudget is an automated budgeting app for Android and iOS which syncs with your bank account and helps you avoid overspending. If you’d like to quit living paycheck-to-paycheck and get a better handle on your finances, download it today! https://bitbudget.io

<!DOCTYPE html>
<html>
<head>
<!-- Mobile Friendly Meta Tag -->
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<h1>Vanilla TODO</h1>
<input type="text" id="newItem">
<button onclick="addToList();">+</button>
<ul id="todoList"></ul>
<script>
function addToList() {
var task = document.getElementById("newItem").value;
var thingtoadd = document.createElement("LI");
thingtoadd.innerHTML = task;
thingtoadd.id = Math.random().toString();
var removebutton = document.createElement("BUTTON");
removebutton.innerHTML = "X";
removebutton.onclick = function() {
removeFromList(thingtoadd.id);
};
thingtoadd.appendChild(removebutton);
// thingtoadd.innerHTML += removebutton;
var todoList = document.getElementById("todoList");
todoList.appendChild(thingtoadd);
/*
thingtoadd.onclick = function() {
removeFromList(thingtoadd.id);
};
*/
console.log(task);
}
function removeFromList(id) {
var todoList = document.getElementById("todoList"); // parent
var itemToBeRemoved = document.getElementById(id); // child
todoList.removeChild(itemToBeRemoved);
}
</script>
</body>
</html>
 

React Native error Failed to install the app… com.android.ddmlib.InstallException: INSTALL_FAILED_UPDATE_INCOMPATIBLE: Package signatures do not match previously installed version; ignoring!

This blog post is brought to you by the developer of BitBudget. BitBudget is an automated budgeting app for Android and iOS which syncs with your bank account and helps you avoid overspending. If you’d like to quit living paycheck-to-paycheck and get a better handle on your finances, download it today! https://bitbudget.io

error Failed to install the app. Make sure you have the Android development environment set up: https://facebook.github.io/react-native/docs/getting-started.html#android-development-environment. Run CLI with –verbose flag for more details.

Error: Command failed: gradlew.bat app:installDebug -PreactNativeDevServerPort=8081

Unable to install C:\Users\you\Desktop\YourApp\android\app\build\outputs\apk\debug\app-debug.apk

com.android.ddmlib.InstallException: INSTALL_FAILED_UPDATE_INCOMPATIBLE: Package com.yourapp signatures do not match previously installed version; ignoring!

O man, what a doozy!?! Okay so here’s what’s probably going on, or at least what has been going on the several times I’ve run into this error. I happen to do development on several different computers, but use the same physical android device to test my app. So what happens is, the signature attached to the app installed on our physical android device, doesn’t match the signature of the computer that we’ve moved to and are now working.

However, the fix is fairly simple. All you need to do is delete the app from your physical device, then re-build/run your app again and all shall be well!

$ npx react-native run-android

or…

$ react-native run-android