@jamesob
a little background on the codebase at Percolate
Multiple repos, a few services, but we do have a core codebase
http://cloc.sourceforge.net v 1.56
--------------------------------------------------
Language files code
--------------------------------------------------
Python 822 120613
Javascript 1068 76590
HTML 570 27181
SQL 32 2518
CSS 14 2444
YAML 2 848
Bourne Shell 23 358
Bourne Again Shell 3 201
Ruby 1 47
--------------------------------------------------
SUM: 2535 230800
--------------------------------------------------
so: roughly 120k lines of python
(including tests & doc)
not a crisis, but not a trend to continue
how do we address this?
redset
set
interface
import json
from redset import TimeSortedSet
ss = TimeSortedSet(redis.Redis(), 'so-much-work', serializer=json)
ss.add({'task': 1})
ss.add({'task': 2})
# from some other process...
ss.pop() # -> {'task': 1}
# monitor age of oldest task in set
send_to_graphite('work-delay', time.time() - ss.peek_score())
lightweight, multiprocess-friendly sets
are useful all over the GD place
these opportunities for reuse were only realized after the package was broken out of the main app
coverage
is useful again!
nosetests --with-cov --cov-report term-missing --cov redset tests
.....................
---------- coverage: platform linux2, python 2.7.4-final-0 --------
Name Stmts Miss Cover Missing
-------------------------------------------------
redset/__init__ 2 0 100%
redset/exceptions 2 0 100%
redset/interfaces 5 0 100%
redset/locks 25 2 92% 65, 70
redset/sets 90 6 93% 52, 61, 262-263, 274-275
-------------------------------------------------
TOTAL 124 8 94%
-------------------------------------------------------------------
Ran 21 tests in 2.152s
OK
there are real benefits to modularizing + packaging
(this section is a brief rehash of this excellent article by Jeff Knupp)
redset
├── docs # sphinx
│ ├── conf.py
│ ├── index.rst
│ ├── Makefile
│ ├── _static
│ └── _templates
├── HISTORY.md # changelog
├── LICENSE
├── README.md
├── redset # python package
│ ├── __init__.py
│ ├── exceptions.py
│ ├── interfaces.py
│ ├── locks.py
│ └── sets.py
├── setup.py
├── requirements.txt # if we have dependencies
└── tests # mandatory ;)
├── __init__.py
├── test_concurrency.py
└── test_sets.py
be sure to spend some time on your setup.py, as this will control your package's pypi presence.
automodule
, autoclass
, et alcoverage
as a guideyour package is all dolled up; now what?
setup.py
easier than it sounds
python setup.py register
python setup.py sdist upload
# boom, done
CI is awesome. travis is reaallly awesome.
language: python
python:
- "2.7"
# requires redis-server for multiprocess tests
services:
- redis-server
# command to install dependencies
install:
- "pip install redis"
- "pip install ."
# command to run tests
script: nosetests
my dog literally wrote this config file
(and he even hates YAML)
benefit/effort ratio is really high
these peripheral services aren't just niceties