On the prompting of [Jason Myers](https://thoughtstreams.io/jasonamyers/), I'm going to try my best to keep a journal of little code puzzles and improvements that I make in the course of writing and maintaining open source code in my never ending search for higher quality code. ---- Recently, I've been doing a lot of work prepping a relaunch of django-stripe-payments, renamed along the way to [pinax-stripe](http://github.com/pinax/pinax-stripe). In this process, I have gone down the rabbit hole of trying all kinds of static analysis things to help inform and drive quality up. ---- A recent thing that Jason brought to my attention today was [bandit](http://github.com/openstack/bandit). So without delay, I installed and ran it with defaults against `pinax-stripe`. It reported three issues that previous static analyzers failed to point out: ``` Run metrics: Total lines of code: 2547 Total lines skipped (#nosec): 0 Total issues (by severity): Undefined: 0.0 Low: 3.0 Medium: 0.0 High: 0.0 Total issues (by confidence): Undefined: 0.0 Low: 0.0 Medium: 0.0 High: 3.0 ``` All three issues were cases of using `pass` in a `try/except` block. ---- The full details of my fixes can be found in [this commit](https://github.com/pinax/pinax-stripe/commit/72f97e8d66e5cd2e3f1e2ee12fbb55d577295343?diff=split). I'd like to point the fixes individually though as well: The [first example](https://github.com/pinax/pinax-stripe/commit/72f97e8d66e5cd2e3f1e2ee12fbb55d577295343?diff=split#diff-b46b4ff78f8c8f8e951ee3a56eac38a9R86) was just a case of reversing the logic so that I only re-raise the exception if it's not the thing we want to ignore. No wizardry there. The [next fix](https://github.com/pinax/pinax-stripe/commit/72f97e8d66e5cd2e3f1e2ee12fbb55d577295343?diff=split#diff-b46b4ff78f8c8f8e951ee3a56eac38a9R114) is probably one of my favorite tricks. Often you want to effectively retrieve a single object or return None. It's ok if it doesn't exist and if multiple exist you just need the first one. You can either write a queryset check the count or exists before indexing into it, or wrap a get in a try/except (which is what I originally had in this case), or you can use `next` and `iter` do things in a single line and single query. In this example, it was: customer = next(iter(queryset)), None) Then you can check if the `customer` is None and act on it accordingly. The [third fix](https://github.com/pinax/pinax-stripe/commit/72f97e8d66e5cd2e3f1e2ee12fbb55d577295343?diff=split#diff-c899278b424ff93100901f3270955a1eR23) was simply checking for the existence of the field name in a way that wouldn't raise an exception. In this specific case, I want to add the ability to search by a user's email if the user model in question has an email field like the default `django.contrib.auth.User` has. In the [fourth and last fix](https://github.com/pinax/pinax-stripe/commit/72f97e8d66e5cd2e3f1e2ee12fbb55d577295343?diff=split#diff-1bb20dfc2cde5b3994d82429b75dfa1eR8) I simply needed to use the `.get()` method on the `response` object then I could avoid needing to worry about the `KeyError` all together. ---- I'm gonna use this to publish some random things I encounter in my dev work. ---- Always run `git clean -fdx` prior to creating a Python release to eliminate possibility of unknown bits getting including in your package. Discovered a file I had deleted from a previous release laying around in a `build/` directory that was getting shipped with subsequent releases somehow, but only in the `wheel` releases, not the standard `sdist`. ---- # Setting up my Ubuntu Dev environments 1. Install Ubuntu (Whatever flavor you like) 2. sudo apt-get upgrade && sudo apt-get upgrade 3. Copy over SSH keys 4. chmod 600 .ssh/* 5. sudo apt-get install emacs git vim make gnome-tweak-tool curl build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget llvm libncurses5-dev 6. Run Tweak Tool -> Click Typing -> set Caps Lock key behavior to "Make Caps Lock an additional Ctrl" -> set Alt/Win key behavior to "Alt and Meta are on Alt keys" 7. Setup Firefox Sync 8. Copy down dotfiles: git clone git@github.com:jasonamyers/dots 9. cd dots 10. ./setup.sh 11. rm .emacs.d 12. Copy down emacs dotfiles: git clone git@github.com:jasonamyers/prelude .emacs.d 13. Setup pyenv: curl -L https://raw.githubusercontent.com/yyuu/pyenv-installer/master/bin/pyenv-installer | bash 14. Setup pyenv-virtualenvwrapper: git clone https://github.com/yyuu/pyenv-virtualenvwrapper.git ~/.pyenv/plugins/pyenv-virtualenvwrapper 15. Install Python 2.7.11: pyenv install 2.7.11 16. Install Python 3.5.1: pyenv install 3.5.1 17. Install nvm: curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.29.0/install.sh | bash 18. Download the lastest version of Go from https://golang.org/dl/ 19. Install Go: sudo tar -C /usr/local -xzf go1.5.2.linux-amd64.tar.gz 20. Install Rust: curl -sSf https://static.rust-lang.org/rustup.sh | sh 21. Download Hack Font: http://sourcefoundry.org/hack/ 22. Install Hack Font: cd ~/Downloads && unzip Hack-v2_018-ttf.zip && mv *.ttf ~/.fonts/ && fc-cache 23. Setup go-mode: mkdir -p ~/Misc/emacs && cd ~/Misc/emacs && git clone git@github.com:dominikh/go-mode.el.git 24 Open emacs, it will compile for a while and end in an error about go auto loads 25. Run M-x update-file-autoloads, Use "~/Misc/emacs/go-mode.el/go-mode.el" as the first answer, and "~/Misc/emacs/go-mode.el/go-mode-el.load" as the autoloads files 26. Exit and Save emacs 27. Install goimports: go get golang.org/x/tools/cmd/goimports 28. Install oracle: go get golang.org/x/tools/cmd/oracle && sudo mv $GOPATH/bin/oracle $GOROOT/bin/ 29. Setup emacs for rust: git clone https://github.com/phildawes/racer.git /tmp/racer && cd /tmp/racer && cargo build --release && mv /tmp/racer/target/release/racer /usr/local/bin && cd ~ && rm -rf /tmp/racer 30. Download rust source for autocompletion: git clone https://github.com/rust-lang/rust.git ~/.rust 28. Test it with: racer complete std::io::B ---- In Django forms, you can either use `exclude` or `fields` to list a set of fields to exclude or include on the `ModelForm`. I prefer to use `fields` to explicitly include fields on a form because it's easy to add fields to a model without thinking through it's use on a form somewhere in your project. However, if you are adding a field for the purpose of adding it to a form you'll have the form in mind so explicitly adding the field to the `fields` list will not be forgotten about.