Compare commits

..

83 Commits

Author SHA1 Message Date
kennethreitz c77a1877d3 v98 2017-02-15 13:49:08 -05:00
kennethreitz 1c51f5d84e NLTK support 2017-02-15 13:44:31 -05:00
kennethreitz 6922a82536 Update README.md 2017-02-01 15:12:21 -05:00
kennethreitz 9cc5bf1a85 Update README.md 2017-02-01 15:11:25 -05:00
kennethreitz 012cb8a4df Added more tests 2017-02-01 15:09:49 -05:00
kennethreitz fab60ae6ab more tests 2017-01-24 23:16:36 -05:00
kennethreitz cd52da6155 tell travis to run the tests 2017-01-24 23:16:36 -05:00
David Zülke acd9347930 Handle and produce leading 0 in WEB_CONCURRENCY (#355)
The Node buildpack now exports a leading zero in its numbers. This lets us detect that it (or another buildpack) set the value, and overwrite it accordingly.

Fixes the issue where adding the node buildpack to a Python app would cause only one gunicorn worker to be spawned for a 1X dyno, and not two.

We also need to again produce leading zeroes in the value, so that e.g. the PHP buildpack can do the same on boot.
2017-01-23 01:29:02 -05:00
kennethreitz d7e2f0fb08 v97 2017-01-02 11:50:49 -05:00
kennethreitz a3ed9c7155 Fix egg-links
commit cb2c57dcffe856ad547ad8fbd1907815713dc4a7
Author: Kenneth Reitz <me@kennethreitz.org>
Date:   Mon Jan 2 11:44:39 2017 -0500

    no files were found

commit 38f861f6c6dbb2825c6551f220e610bea619c27f
Author: Kenneth Reitz <me@kennethreitz.org>
Date:   Mon Jan 2 11:37:35 2017 -0500

    uninstall

commit db1db5d2a0ad364d646d378ccff62b9aa0257efd
Author: Kenneth Reitz <me@kennethreitz.org>
Date:   Mon Jan 2 11:36:41 2017 -0500

    pip cleanup

commit 2e16f233849f683ad9c9d00bad51c2dd5da11c18
Author: Kenneth Reitz <me@kennethreitz.org>
Date:   Mon Jan 2 11:35:13 2017 -0500

    uninstall

commit 078e43d2926b77a40f21026969ee930aa7ad0fee
Author: Kenneth Reitz <me@kennethreitz.org>
Date:   Mon Jan 2 11:31:39 2017 -0500

    fix

commit eff318eaf37161f0c496e130688b27d596b9cd7a
Author: Kenneth Reitz <me@kennethreitz.org>
Date:   Mon Jan 2 11:30:09 2017 -0500

    wfwef

commit d8955b452190b1b6a40049c94df564144c4607dc
Author: Kenneth Reitz <me@kennethreitz.org>
Date:   Mon Jan 2 11:28:30 2017 -0500

    oops

commit 0e83a0ae238bdea06ce0d184c8139b598f71745e
Author: Kenneth Reitz <me@kennethreitz.org>
Date:   Mon Jan 2 11:24:28 2017 -0500

    find

commit b9cb901ecb9d9075020f5c63e5faee04aade1ad7
Author: Kenneth Reitz <me@kennethreitz.org>
Date:   Mon Jan 2 11:23:04 2017 -0500

    don't

commit 3fd1a448e244a7c3f877ae75cd8672ef42a3f550
Author: Kenneth Reitz <me@kennethreitz.org>
Date:   Mon Jan 2 11:22:29 2017 -0500

    output

commit 884c6a40ee14365fccd4c9a34fb7733a833303a4
Author: Kenneth Reitz <me@kennethreitz.org>
Date:   Mon Jan 2 11:17:47 2017 -0500

    delete egg links

commit 9a16a8676abbd34b9ae0de3de4d52b4d358b2e35
Author: Kenneth Reitz <me@kennethreitz.org>
Date:   Mon Jan 2 11:14:18 2017 -0500

    remove egg-links

commit d45d9e977adc8ad7c5c18a27f1dfb20eb286bb5d
Author: Kenneth Reitz <me@kennethreitz.org>
Date:   Mon Jan 2 10:35:24 2017 -0500

    no echo

commit 5cfb64387db1c69fff57ac9afa0c996a34a4362d
Author: Kenneth Reitz <me@kennethreitz.org>
Date:   Mon Jan 2 10:33:58 2017 -0500

    debug

commit ac143097e9ee0a23464d16e2c6d414437046132e
Author: Kenneth Reitz <me@kennethreitz.org>
Date:   Mon Jan 2 10:26:27 2017 -0500

    no print 0

commit 72adfe2e4abd975f5df5350f06f93d1309ff4ed1
Author: Kenneth Reitz <me@kennethreitz.org>
Date:   Mon Jan 2 10:25:27 2017 -0500

    cat other one

commit e51e83ca3ec9a6710add90424f80f9bc7c3d5bf3
Author: Kenneth Reitz <me@kennethreitz.org>
Date:   Mon Jan 2 10:23:52 2017 -0500

    echo

commit def0231dd068fe4a854074bf42409ef373ac0977
Author: Kenneth Reitz <me@kennethreitz.org>
Date:   Mon Jan 2 10:20:31 2017 -0500

    cat the files
2017-01-02 11:48:45 -05:00
matsulib 8db1f07fba Update README.md (#354) 2016-12-30 20:17:21 -05:00
kennethreitz 17081d0328 Squashed commit of the following:
commit b611ff0cd6ed05ff27a42b6c2da656441056cfba
Author: Kenneth Reitz <me@kennethreitz.org>
Date:   Fri Dec 23 23:11:51 2016 -0500

    remove debugging statements

commit d1ab87748b
Author: Kenneth Reitz <me@kennethreitz.org>
Date:   Fri Dec 23 23:05:46 2016 -0500

    ln -s

commit 6844d1252d
Author: Kenneth Reitz <me@kennethreitz.org>
Date:   Fri Dec 23 22:55:41 2016 -0500

    further debug

commit 1346c29089
Author: Kenneth Reitz <me@kennethreitz.org>
Date:   Fri Dec 23 22:54:42 2016 -0500

    debug

commit 3bc1b5e697
Author: Kenneth Reitz <me@kennethreitz.org>
Date:   Fri Dec 23 22:53:23 2016 -0500

    say when installing pip or setuptools
2016-12-23 23:24:34 -05:00
kennethreitz 9a6fa0478a Python 3.6.0 2016-12-23 12:51:20 -05:00
Jason Dusek 573ded6d41 Idempotency in symlink creation (#349) 2016-12-21 23:23:35 -05:00
kennethreitz b4ec35433a v96 2016-12-21 01:58:54 -05:00
kennethreitz cf1148f0a8 keep things in place 2016-12-20 14:04:17 -05:00
kennethreitz a0649b1e50 move things around for collectstatic 2016-12-20 14:03:12 -05:00
kennethreitz 2f2fd24421 v95 2016-12-20 13:48:47 -05:00
kennethreitz f754ae16bb capture stderr 2016-12-20 13:47:25 -05:00
kennethreitz cef1be80a5 silence find output 2016-12-20 13:41:06 -05:00
kennethreitz c0571d86bf don't fail 2016-12-20 13:39:26 -05:00
kennethreitz d82eddca03 support for pypy 2016-12-20 13:35:44 -05:00
kennethreitz 119e8145c3 move .src up for collectstatic 2016-12-20 12:09:51 -05:00
kennethreitz 99dae0f671 v92 2016-12-19 22:16:11 -05:00
kennethreitz f54dfff8a9 fix permission denied 2016-12-19 22:12:57 -05:00
kennethreitz c9760ae0ee fix deep-cp 2016-12-19 22:09:51 -05:00
kennethreitz 98ff1670b3 cleanup 2016-12-19 22:05:28 -05:00
kennethreitz bdd466f838 cleanup pip install steps, caching src 2016-12-19 22:04:51 -05:00
kennethreitz 324ebc9223 attempted fix 2016-12-19 18:03:13 -05:00
kennethreitz 42ec6d8701 remove extra stuff 2016-12-19 17:59:02 -05:00
kennethreitz 19513067bb Merge branch 'dash-e'
# Conflicts:
#	bin/compile
2016-12-19 17:58:02 -05:00
kennethreitz 753c912ecc changelog 2016-12-19 17:53:01 -05:00
kennethreitz 4e8c469ec7 deep copy 2016-12-19 17:50:31 -05:00
kennethreitz 852723f867 find all *.pth files for sed replacement 2016-12-19 16:58:31 -05:00
David Zuelke 94514a8179 fix egg links containing refs to /tmp 2016-12-19 22:52:46 +01:00
kennethreitz 7d57744c0a v90 2016-12-19 16:49:24 -05:00
kennethreitz a41ddf6bd1 skip set if no path-links are found 2016-12-19 16:48:30 -05:00
kennethreitz 197b7bae3f Merge branch 'egg-links' 2016-12-19 16:45:16 -05:00
kennethreitz f468739cfb v89 2016-12-19 16:45:04 -05:00
kennethreitz 555d5bd2be cp the cache 2016-12-19 16:42:33 -05:00
kennethreitz 0a4d32c8a5 cache src 2016-12-19 16:39:34 -05:00
kennethreitz 1a1cedfc21 symlink eggs 2016-12-19 16:37:03 -05:00
kennethreitz d35ee2c14c Squashed commit of the following:
commit 554a8bbae6
Author: Kenneth Reitz <me@kennethreitz.org>
Date:   Mon Dec 19 16:26:18 2016 -0500

    comment out debugging line

commit 6572ad3d44
Author: Kenneth Reitz <me@kennethreitz.org>
Date:   Mon Dec 19 16:21:03 2016 -0500

    test

commit 35cabaeebc
Author: Kenneth Reitz <me@kennethreitz.org>
Date:   Mon Dec 19 16:09:21 2016 -0500

    try .

commit 300285a92d
Author: Kenneth Reitz <me@kennethreitz.org>
Date:   Mon Dec 19 16:05:22 2016 -0500

    find

commit 7a6f1eb010
Author: Kenneth Reitz <me@kennethreitz.org>
Date:   Mon Dec 19 16:02:24 2016 -0500

    find

commit 66d754978e
Author: Kenneth Reitz <me@kennethreitz.org>
Date:   Mon Dec 19 15:55:04 2016 -0500

    fix xargs

commit 9c222a9350
Author: Kenneth Reitz <me@kennethreitz.org>
Date:   Mon Dec 19 15:53:04 2016 -0500

    copy src

commit 7f4273f47f
Author: Kenneth Reitz <me@kennethreitz.org>
Date:   Mon Dec 19 15:45:20 2016 -0500

    new replace script

commit dd707c21e3
Author: Kenneth Reitz <me@kennethreitz.org>
Date:   Mon Dec 19 15:40:35 2016 -0500

    re-write egg-links
2016-12-19 16:31:29 -05:00
kennethreitz 554a8bbae6 comment out debugging line 2016-12-19 16:26:18 -05:00
kennethreitz 6572ad3d44 test 2016-12-19 16:21:03 -05:00
kennethreitz 35cabaeebc try . 2016-12-19 16:09:21 -05:00
kennethreitz 300285a92d find 2016-12-19 16:05:22 -05:00
kennethreitz 7a6f1eb010 find 2016-12-19 16:02:24 -05:00
kennethreitz 66d754978e fix xargs 2016-12-19 15:55:04 -05:00
kennethreitz 9c222a9350 copy src 2016-12-19 15:53:04 -05:00
kennethreitz 7f4273f47f new replace script 2016-12-19 15:45:20 -05:00
kennethreitz dd707c21e3 re-write egg-links 2016-12-19 15:40:35 -05:00
kennethreitz 7833743f96 don't change to /app 2016-12-19 15:19:32 -05:00
kennethreitz 5a9155e311 build dir for pip 2016-12-19 15:04:57 -05:00
kennethreitz 857c47ad66 /app for pip 2016-12-19 15:02:14 -05:00
kennethreitz 87cf6073dc add note about /app/.heroku/src 2016-12-18 13:58:22 -05:00
kennethreitz 36dd089808 cleanup indentation 2016-12-18 13:57:30 -05:00
kennethreitz c58f52e06e remove purging of old virtualenvs
since old stacks aren't supported
2016-12-18 13:56:16 -05:00
kennethreitz 265a95d3b6 v88 2016-12-18 13:53:09 -05:00
kennethreitz 290c1377fb Revert "see if symlink works now"
This reverts commit 8e42040d01.
2016-12-18 13:51:03 -05:00
kennethreitz 8e42040d01 see if symlink works now 2016-12-18 13:48:48 -05:00
kennethreitz d8755e6791 be specific in pip install directory 2016-12-18 13:44:10 -05:00
kennethreitz 364a1fafd9 -e fixings 2016-12-18 13:31:22 -05:00
kennethreitz 251b7f7960 copy the -e directory instead of symlinking 2016-12-18 13:26:47 -05:00
kennethreitz 6d491f9f2b fix for -e 2016-12-18 13:16:49 -05:00
kennethreitz 7cfbce82fd remove bunk autoconf 2016-12-17 21:15:28 -05:00
kennethreitz d520ca4291 new pypys 2016-12-17 19:21:39 -05:00
kennethreitz bf252422fc attempted fix for pypy 2016-12-17 19:12:18 -05:00
kennethreitz d7874d583b move v87 notes 2016-12-17 18:59:44 -05:00
kennethreitz d32dc82e1c v87 2016-12-17 18:58:58 -05:00
kennethreitz bd048d50b5 update default python to 2.7.13 2016-12-17 18:58:51 -05:00
kennethreitz 26b2eeee20 update setuptools to v31.1.0 2016-12-17 18:58:32 -05:00
kennethreitz e527457ba3 Merge branch 'master' of heroku.com:python-builder-cedar-14 2016-12-17 18:48:19 -05:00
kennethreitz 1b7bd02bf2 Merge branch 'master' into docker-builds 2016-12-16 20:25:00 -05:00
kennethreitz de9b0b9383 v86 2016-12-16 20:24:07 -05:00
David Zülke 991f4126d7 Greatly simplify code copying (#340)
* drop duplicate mkdir for .heroku

* simplify linking and moving of python and source

* steps/python needs its own symlink setup

* fix symlink destinations for vendor and venv

* always symlink python
2016-12-16 17:13:57 -08:00
kennethreitz 076a457ad9 changes 2016-12-16 11:08:49 -05:00
kennethreitz 264f74d159 skip binaries for heroku-16 2016-12-15 16:10:37 -05:00
kennethreitz 9f89c4e744 bob-builder==0.0.5 2016-12-15 13:52:53 -05:00
kennethreitz 8d2788094b python-2.7.13 with UCS-4 2016-12-15 13:20:51 -05:00
kennethreitz e2f4fd442a dockerfile for bob-builder 2016-12-14 16:00:32 -05:00
kennethreitz 28b67dd208 update pypy formula 2016-08-19 08:57:19 -04:00
kennethreitz 24f73fbc2d pypi workaround 2016-08-19 08:54:24 -04:00
31 changed files with 2046 additions and 98 deletions
+6 -2
View File
@@ -1,2 +1,6 @@
sudo: false language: bash
script: exit 0 sudo: required
services:
- docker
install: docker pull heroku/cedar:14
script: make test
+61 -3
View File
@@ -1,8 +1,66 @@
# Python Buildpack Changelog # Python Buildpack Changelog
## 98
Official NLTK support and other improvements.
- Support for `nltk.txt` file for declaring corpora to be downloaded.
- Leading zeros for auto-set WEB_CONCURRENCY.
## 97
Improved egg-link functionality.
## 96
Bugfix.
## 95
Improved output support.
## v94
Improved support for PyPy.
## v93
Improved support for PyPy.
## v92
Improved cache functionality and fix egg-links regression.
## v91
Bugfix, rolled back to v88.
## v90
Bugfix.
## v89
Improved cache functionality and fix egg-links regression.
## v88
Fixed bug with editable pip installations.
## v87
Updated default Python 2.7.13.
- Python 2.7.13 uses UCS-4 build, more compatibile with linux wheels.
- Updated setuptools to v32.1.0.
## v86
Refactor and multi-buildpack compatibility.
## v85 ## v85
Packaging fix. Packaging fix.
## v84 ## v84
@@ -27,8 +85,8 @@ Update to library detection mechnisms (pip-pop).
Updated default Python to 2.7.11. Updated default Python to 2.7.11.
- Updated setuptools to v8.1.2. - Updated pip to v8.1.2.
- Updated pip to v23.1.0. - Updated setuptools to v23.1.0.
## v80 (2016-04-05) ## v80 (2016-04-05)
+11
View File
@@ -0,0 +1,11 @@
FROM heroku/heroku:16-build
WORKDIR /app
ENV WORKSPACE_DIR=/app/builds
RUN apt-get update && apt-get install -y python-pip
# Install bob-builder application
RUN pip install bob-builder==0.0.5
COPY . /app
+6 -2
View File
@@ -1,8 +1,12 @@
# These targets are not files # These targets are not files
.PHONY: tests .PHONY: tests
tests: test: test-cedar-14
./bin/test
test-cedar-14:
@echo "Running tests in docker (cedar-14)..."
@docker run -v $(shell pwd):/buildpack:ro --rm -it -e "STACK=cedar-14" heroku/cedar:14 bash -c 'cp -r /buildpack /buildpack_test; cd /buildpack_test/; test/run;'
@echo ""
tools: tools:
git clone https://github.com/kennethreitz/pip-pop.git git clone https://github.com/kennethreitz/pip-pop.git
+10 -8
View File
@@ -2,6 +2,8 @@
# Heroku Buildpack: Python # Heroku Buildpack: Python
[![Build Status](https://travis-ci.org/heroku/heroku-buildpack-python.svg?branch=master)](https://travis-ci.org/heroku/heroku-buildpack-python)
This is the official [Heroku buildpack](https://devcenter.heroku.com/articles/buildpacks) for Python apps, powered by [pip](https://pip.pypa.io/) and other excellent software. This is the official [Heroku buildpack](https://devcenter.heroku.com/articles/buildpacks) for Python apps, powered by [pip](https://pip.pypa.io/) and other excellent software.
Recommended web frameworks include **Django** and **Flask**. The recommended webserver is **Gunicorn**. There are no restrictions around what software can be used (as long as it's pip-installable). Web processes must bind to `$PORT`, and only the HTTP protocol is permitted for incoming connections. Recommended web frameworks include **Django** and **Flask**. The recommended webserver is **Gunicorn**. There are no restrictions around what software can be used (as long as it's pip-installable). Web processes must bind to `$PORT`, and only the HTTP protocol is permitted for incoming connections.
@@ -21,12 +23,12 @@ Deploying a Python application couldn't be easier:
$ git push heroku master $ git push heroku master
... ...
-----> Python app detected -----> Python app detected
-----> Installing python-2.7.12 -----> Installing python-2.7.13
$ pip install -r requirements.txt $ pip install -r requirements.txt
Collecting requests (from -r requirements.txt (line 1)) Collecting requests (from -r requirements.txt (line 1))
Downloading requests-2.10.0-py2.py3-none-any.whl (501kB) Downloading requests-2.12.4-py2.py3-none-any.whl (576KB)
Installing collected packages: requests Installing collected packages: requests
Successfully installed requests-2.10.0 Successfully installed requests-2.12.4
-----> Discovering process types -----> Discovering process types
Procfile declares types -> (none) Procfile declares types -> (none)
@@ -44,11 +46,11 @@ Specify a Python Runtime
Specific versions of the Python runtime can be specified with a `runtime.txt` file: Specific versions of the Python runtime can be specified with a `runtime.txt` file:
$ cat runtime.txt $ cat runtime.txt
python-3.5.2 python-3.6.0
Runtime options include: Runtime options include:
- `python-2.7.12` - `python-2.7.13`
- `python-3.5.2` - `python-3.6.0`
- `pypy-5.3.1` (unsupported, experimental) - `pypy-5.6.0` (unsupported, experimental)
- `pypy3-2.4.0` (unsupported, experimental) - `pypy3-5.5.0` (unsupported, experimental)
+46 -61
View File
@@ -31,11 +31,11 @@ ENV_DIR=$3
VIRTUALENV_LOC=".heroku/venv" VIRTUALENV_LOC=".heroku/venv"
LEGACY_TRIGGER="lib/python2.7" LEGACY_TRIGGER="lib/python2.7"
DEFAULT_PYTHON_VERSION="python-2.7.12" DEFAULT_PYTHON_VERSION="python-2.7.13"
DEFAULT_PYTHON_STACK="cedar-14" DEFAULT_PYTHON_STACK="cedar-14"
PYTHON_EXE="/app/.heroku/python/bin/python" PYTHON_EXE="/app/.heroku/python/bin/python"
PIP_VERSION="9.0.1" PIP_VERSION="9.0.1"
SETUPTOOLS_VERSION="28.8.0" SETUPTOOLS_VERSION="32.1.0"
# Common Problem Warnings # Common Problem Warnings
export WARNINGS_LOG=$(mktemp) export WARNINGS_LOG=$(mktemp)
@@ -54,7 +54,6 @@ export PATH=$PATH:$ROOT_DIR/vendor/pip-pop
[ ! "$SLUG_ID" ] && SLUG_ID="defaultslug" [ ! "$SLUG_ID" ] && SLUG_ID="defaultslug"
[ ! "$REQUEST_ID" ] && REQUEST_ID=$SLUG_ID [ ! "$REQUEST_ID" ] && REQUEST_ID=$SLUG_ID
[ ! "$STACK" ] && STACK=$DEFAULT_PYTHON_STACK [ ! "$STACK" ] && STACK=$DEFAULT_PYTHON_STACK
[[ $BUILD_DIR == "/app" ]] && SKIP_MOVE_BUILD=1
# Sanitizing environment variables. # Sanitizing environment variables.
unset GIT_DIR PYTHONHOME PYTHONPATH unset GIT_DIR PYTHONHOME PYTHONPATH
@@ -64,7 +63,6 @@ unset CYTOKINE_LOG_FILE GEM_PATH
# Setup buildpack instrumentation. # Setup buildpack instrumentation.
bpwatch init $LOGPLEX_KEY bpwatch init $LOGPLEX_KEY
bpwatch build python $BUILDPACK_VERSION $REQUEST_ID bpwatch build python $BUILDPACK_VERSION $REQUEST_ID
TMP_APP_DIR=$CACHE_DIR/tmp_app_dir
bpwatch start compile bpwatch start compile
@@ -74,33 +72,8 @@ source $BIN_DIR/utils
# Import collection of warnings. # Import collection of warnings.
source $BIN_DIR/warnings source $BIN_DIR/warnings
# Directory Hacks for path consistency. # we need to put a bunch of symlinks in there later
APP_DIR='/app' mkdir -p /app/.heroku
TMP_APP_DIR=$CACHE_DIR/tmp_app_dir
# Skip these steps for Docker.
if [[ ! "$SKIP_MOVE_BUILD" ]]; then
# Copy Anvil app dir to temporary storage...
bpwatch start anvil_appdir_stage
if [ "$SLUG_ID" ]; then
mkdir -p $TMP_APP_DIR
deep-mv $APP_DIR $TMP_APP_DIR
else
deep-rm $APP_DIR
fi
bpwatch stop anvil_appdir_stage
# Copy Application code in.
bpwatch start appdir_stage
deep-cp $BUILD_DIR $APP_DIR
bpwatch stop appdir_stage
fi
# Set new context.
ORIG_BUILD_DIR=$BUILD_DIR
BUILD_DIR=$APP_DIR
# Set up outputs under new context # Set up outputs under new context
PROFILE_PATH="$BUILD_DIR/.profile.d/python.sh" PROFILE_PATH="$BUILD_DIR/.profile.d/python.sh"
@@ -111,14 +84,14 @@ GUNICORN_PROFILE_PATH="$BUILD_DIR/.profile.d/python.gunicorn.sh"
export BUILD_DIR CACHE_DIR BIN_DIR PROFILE_PATH EXPORT_PATH export BUILD_DIR CACHE_DIR BIN_DIR PROFILE_PATH EXPORT_PATH
# Prepend proper environment variables for Python use. # Prepend proper environment variables for Python use.
export PATH=$BUILD_DIR/.heroku/python/bin:$BUILD_DIR/.heroku/vendor/bin:$PATH export PATH=/app/.heroku/python/bin:/app/.heroku/vendor/bin:$PATH
export PYTHONUNBUFFERED=1 export PYTHONUNBUFFERED=1
export LANG=en_US.UTF-8 export LANG=en_US.UTF-8
export C_INCLUDE_PATH=/app/.heroku/vendor/include:$BUILD_DIR/.heroku/vendor/include:/app/.heroku/python/include:$C_INCLUDE_PATH export C_INCLUDE_PATH=/app/.heroku/vendor/include:/app/.heroku/python/include:$C_INCLUDE_PATH
export CPLUS_INCLUDE_PATH=/app/.heroku/vendor/include:$BUILD_DIR/.heroku/vendor/include:/app/.heroku/python/include:$CPLUS_INCLUDE_PATH export CPLUS_INCLUDE_PATH=/app/.heroku/vendor/include:/app/.heroku/python/include:$CPLUS_INCLUDE_PATH
export LIBRARY_PATH=/app/.heroku/vendor/lib:$BUILD_DIR/.heroku/vendor/lib:/app/.heroku/python/lib:$LIBRARY_PATH export LIBRARY_PATH=/app/.heroku/vendor/lib:/app/.heroku/python/lib:$LIBRARY_PATH
export LD_LIBRARY_PATH=/app/.heroku/vendor/lib:$BUILD_DIR/.heroku/vendor/lib:/app/.heroku/python/lib:$LD_LIBRARY_PATH export LD_LIBRARY_PATH=/app/.heroku/vendor/lib:/app/.heroku/python/lib:$LD_LIBRARY_PATH
export PKG_CONFIG_PATH=/app/.heroku/vendor/lib/pkg-config:$BUILD_DIR/.heroku/vendor/lib/pkg-config:/app/.heroku/python/lib/pkg-config:$PKG_CONFIG_PATH export PKG_CONFIG_PATH=/app/.heroku/vendor/lib/pkg-config:/app/.heroku/python/lib/pkg-config:$PKG_CONFIG_PATH
# Switch to the repo's context. # Switch to the repo's context.
cd $BUILD_DIR cd $BUILD_DIR
@@ -175,15 +148,23 @@ bpwatch start restore_cache
cp -R $CACHE_DIR/.heroku/python-version .heroku/ &> /dev/null || true cp -R $CACHE_DIR/.heroku/python-version .heroku/ &> /dev/null || true
cp -R $CACHE_DIR/.heroku/vendor .heroku/ &> /dev/null || true cp -R $CACHE_DIR/.heroku/vendor .heroku/ &> /dev/null || true
cp -R $CACHE_DIR/.heroku/venv .heroku/ &> /dev/null || true cp -R $CACHE_DIR/.heroku/venv .heroku/ &> /dev/null || true
if [[ -d $CACHE_DIR/.heroku/src ]]; then
cp -R $CACHE_DIR/.heroku/src .heroku/ &> /dev/null || true
fi
bpwatch stop restore_cache bpwatch stop restore_cache
set +e
# Create set-aside `.heroku` folder.
mkdir .heroku &> /dev/null
set -e
mkdir -p $(dirname $PROFILE_PATH) mkdir -p $(dirname $PROFILE_PATH)
mkdir -p /app/.heroku/src
if [[ $BUILD_DIR != '/app' ]]; then
# python expects to reside in /app, so set up symlinks
# we will not remove these later so subsequent buildpacks can still invoke it
ln -nsf $BUILD_DIR/.heroku/python /app/.heroku/python
ln -nsf $BUILD_DIR/.heroku/vendor /app/.heroku/vendor
ln -nsf $BUILD_DIR/.heroku/venv /app/.heroku/venv
# Note: .heroku/src is copied in later.
fi
# Install Python. # Install Python.
source $BIN_DIR/steps/python source $BIN_DIR/steps/python
@@ -209,13 +190,19 @@ sub-env $BIN_DIR/steps/geo-libs
# GDAL support. # GDAL support.
source $BIN_DIR/steps/gdal source $BIN_DIR/steps/gdal
# Install dependencies with Pip. # Install dependencies with Pip (where the magic happens).
source $BIN_DIR/steps/pip-install source $BIN_DIR/steps/pip-install
# Support for NLTK corpora.
sub-env $BIN_DIR/steps/nltk
# Support for pip install -e.
rm -fr $BUILD_DIR/.heroku/src
deep-cp /app/.heroku/src $BUILD_DIR/.heroku/src
# Django collectstatic support. # Django collectstatic support.
sub-env $BIN_DIR/steps/collectstatic sub-env $BIN_DIR/steps/collectstatic
# Create .profile script for application runtime environment variables. # Create .profile script for application runtime environment variables.
set-env PATH '$HOME/.heroku/python/bin:$PATH' set-env PATH '$HOME/.heroku/python/bin:$PATH'
set-env PYTHONUNBUFFERED true set-env PYTHONUNBUFFERED true
@@ -229,12 +216,21 @@ set-default-env PYTHONPATH /app/
# Install sane-default script for $WEB_CONCURRENCY and $FORWARDED_ALLOW_IPS. # Install sane-default script for $WEB_CONCURRENCY and $FORWARDED_ALLOW_IPS.
cp $ROOT_DIR/vendor/python.gunicorn.sh $GUNICORN_PROFILE_PATH cp $ROOT_DIR/vendor/python.gunicorn.sh $GUNICORN_PROFILE_PATH
# Experimental post_compile hook. # Experimental post_compile hook.
bpwatch start post_compile bpwatch start post_compile
source $BIN_DIR/steps/hooks/post_compile source $BIN_DIR/steps/hooks/post_compile
bpwatch stop post_compile bpwatch stop post_compile
set +e
# rewrite build dir in egg links to /app so things are found at runtime
find .heroku/python/lib/python*/site-packages/ -name "*.pth" -print0 2> /dev/null | xargs -r -0 -n 1 sed -i -e "s#$(pwd)#/app#" &> /dev/null
set -e
set +e
# Support for PyPy
find .heroku/python/lib-python/*/site-packages/ -name "*.pth" -print0 2> /dev/null | xargs -r -0 -n 1 sed -i -e "s#$(pwd)#/app#" &> /dev/null
set -e
# Store new artifacts in cache. # Store new artifacts in cache.
bpwatch start dump_cache bpwatch start dump_cache
@@ -243,6 +239,7 @@ bpwatch start dump_cache
rm -rf $CACHE_DIR/.heroku/python-stack rm -rf $CACHE_DIR/.heroku/python-stack
rm -rf $CACHE_DIR/.heroku/vendor rm -rf $CACHE_DIR/.heroku/vendor
rm -rf $CACHE_DIR/.heroku/venv rm -rf $CACHE_DIR/.heroku/venv
rm -rf $CACHE_DIR/.heroku/src
mkdir -p $CACHE_DIR/.heroku mkdir -p $CACHE_DIR/.heroku
cp -R .heroku/python $CACHE_DIR/.heroku/ cp -R .heroku/python $CACHE_DIR/.heroku/
@@ -250,23 +247,11 @@ bpwatch start dump_cache
cp -R .heroku/python-stack $CACHE_DIR/.heroku/ &> /dev/null || true cp -R .heroku/python-stack $CACHE_DIR/.heroku/ &> /dev/null || true
cp -R .heroku/vendor $CACHE_DIR/.heroku/ &> /dev/null || true cp -R .heroku/vendor $CACHE_DIR/.heroku/ &> /dev/null || true
cp -R .heroku/venv $CACHE_DIR/.heroku/ &> /dev/null || true cp -R .heroku/venv $CACHE_DIR/.heroku/ &> /dev/null || true
if [[ -d .heroku/src ]]; then
cp -R .heroku/src $CACHE_DIR/.heroku/ &> /dev/null || true
fi
bpwatch stop dump_cache bpwatch stop dump_cache
# Fin. # Fin.
if [[ ! "$SKIP_MOVE_BUILD" ]]; then bpwatch stop compile
bpwatch start appdir_commit
deep-rm $ORIG_BUILD_DIR
deep-mv $BUILD_DIR $ORIG_BUILD_DIR
bpwatch stop appdir_commit
bpwatch start anvil_appdir_commit
if [ "$SLUG_ID" ]; then
deep-mv $TMP_APP_DIR $APP_DIR
fi
bpwatch stop anvil_appdir_commit
bpwatch stop compile
fi
Executable
+38
View File
@@ -0,0 +1,38 @@
#!/usr/bin/env bash
# This script serves as the NLTK build step of the
# [**Python Buildpack**](https://github.com/heroku/heroku-buildpack-python)
# compiler.
#
# A [buildpack](https://devcenter.heroku.com/articles/buildpacks) is an
# adapter between a Python application and Heroku's runtime.
#
# This script is invoked by [`bin/compile`](/).
# Syntax sugar.
source $BIN_DIR/utils
bpwatch start nltk_download
export NLTK_DATA_DIR="$BUILD_DIR/nltk_data"
export NLTK_DATA="$BUILD_DIR/nltk_data"
# Check that nltk was installed by pip, otherwise obviously not needed
python -m nltk.downloader -h >/dev/null 2>&1
if [ $? -eq 0 ]; then
puts-step "Downloading NLTK corpora..."
nltk_packages_definition="$BUILD_DIR/nltk.txt"
if [ -f "$nltk_packages_definition" ]; then
nltk_packages=$(tr "\n" " " < "$nltk_packages_definition")
puts-step "Downloading NLTK packages: $nltk_packages"
python -m nltk.downloader -d $BUILD_DIR/.heroku/python/nltk_data $nltk_packages | indent
set-env NLTK_DATA "/app/.heroku/python/nltk_data"
else
puts-warn "nltk.txt not found, not downloading any corpora"
fi
else
puts-warn "nltk not apparently installed, not downloading packages"
fi
bpwatch stop nltk_download
+13 -1
View File
@@ -1,11 +1,23 @@
# Install dependencies with Pip. # Install dependencies with Pip.
puts-cmd "pip install -r requirements.txt" puts-cmd "pip install -r requirements.txt"
set +e
# delete any existing egg links, to uninstall exisisting installations.
find .heroku/python/lib/python*/site-packages/ -name "*.egg-link" -delete 2> /dev/null
find .heroku/python/lib/python*/site-packages/ -name "*.pth" -print0 2> /dev/null | xargs -r -0 -n 1 sed -i -e "s#/app/#/$(pwd)/#" &> /dev/null
set -e
set +e
# Support for the above, for PyPy.
find .heroku/python/lib-python/*/site-packages/ -name "*.egg-link" -print0 2> /dev/null | xargs -r -0 -n 1 sed -i -e "s#/app/#$(pwd)/#" &> /dev/null
find .heroku/python/lib-python/*/site-packages/ -name "*.pth" -print0 2> /dev/null | xargs -r -0 -n 1 sed -i -e "s#/app/#/$(pwd)/#" &> /dev/null
set -e
[ ! "$FRESH_PYTHON" ] && bpwatch start pip_install [ ! "$FRESH_PYTHON" ] && bpwatch start pip_install
[ "$FRESH_PYTHON" ] && bpwatch start pip_install_first [ "$FRESH_PYTHON" ] && bpwatch start pip_install_first
set +e set +e
/app/.heroku/python/bin/pip install -r requirements.txt --exists-action=w --src=./.heroku/src --disable-pip-version-check --no-cache-dir 2>&1 | tee $WARNINGS_LOG | cleanup | indent /app/.heroku/python/bin/pip install -r $BUILD_DIR/requirements.txt --exists-action=w --src=/app/.heroku/src --disable-pip-version-check --no-cache-dir 2>&1 | tee $WARNINGS_LOG | cleanup | indent
PIP_STATUS="${PIPESTATUS[0]}" PIP_STATUS="${PIPESTATUS[0]}"
set -e set -e
+1 -1
View File
@@ -13,7 +13,7 @@ indent() {
# Clean up pip output # Clean up pip output
cleanup() { cleanup() {
sed -e 's/\.\.\.\+/.../g' | sed -e '/already satisfied/Id' | sed -e '/Overwriting/Id' | sed -e '/python executable/Id' | sed -e '/no previously-included files/Id' sed -e 's/\.\.\.\+/.../g' | sed -e '/already satisfied/Id' | sed -e '/No files were found to uninstall/Id' | sed -e '/Overwriting/Id' | sed -e '/python executable/Id' | sed -e '/no previously-included files/Id'
} }
# Buildpack Indented line. # Buildpack Indented line.
-15
View File
@@ -1,15 +0,0 @@
#!/usr/bin/env bash
# Build Path: /app/.heroku/python/
OUT_PREFIX=$1
echo "Building autoconf..."
SOURCE_TARBALL='https://ftp.gnu.org/gnu/autoconf/autoconf-2.68.tar.gz'
curl -L $SOURCE_TARBALL | tar xz
cd autoconf-2.68
./configure --prefix=$OUT_PREFIX
make
make install
+5
View File
@@ -3,6 +3,11 @@
OUT_PREFIX=$1 OUT_PREFIX=$1
# Skip the build for heroku-16.
if [[ $S3_PREFIX == "heroku-16" ]]; then
exit 0
fi
# Use new path, containing autoconf. # Use new path, containing autoconf.
export PATH="/app/.heroku/python/bin/:$PATH" export PATH="/app/.heroku/python/bin/:$PATH"
hash -r hash -r
+5
View File
@@ -3,6 +3,11 @@
OUT_PREFIX=$1 OUT_PREFIX=$1
# Skip the build for heroku-16.
if [[ $S3_PREFIX == "heroku-16" ]]; then
exit 0
fi
# fail hard # fail hard
set -o pipefail set -o pipefail
# fail harder # fail harder
Regular → Executable
View File
+14
View File
@@ -0,0 +1,14 @@
#!/usr/bin/env bash
# Build Path: /app/.heroku/python/
# Build Deps: libraries/sqlite
# NOTICE: This formula only works for the cedar-14 stack, not cedar.
OUT_PREFIX=$1
echo "Building PyPy..."
SOURCE_TARBALL='https://bitbucket.org/pypy/pypy/downloads/pypy3.3-v5.5.0-alpha-linux64.tar.bz2'
curl -L $SOURCE_TARBALL | tar jx
cp -R pypy3-v5.5.0-linux64/* $OUT_PREFIX
ln $OUT_PREFIX/bin/pypy3 $OUT_PREFIX/bin/python
+15
View File
@@ -0,0 +1,15 @@
#!/usr/bin/env bash
# Build Path: /app/.heroku/python/
# Build Deps: libraries/sqlite
OUT_PREFIX=$1
echo "Building Python..."
SOURCE_TARBALL='https://python.org/ftp/python/2.7.13/Python-2.7.13.tgz'
curl -L $SOURCE_TARBALL | tar xz
mv Python-2.7.13 src
cd src
./configure --prefix=$OUT_PREFIX --enable-unicode=ucs4 --with-ensurepip=no
make
make install
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/env bash
# Build Path: /app/.heroku/python/
# Build Deps: libraries/sqlite
OUT_PREFIX=$1
echo "Building Python..."
SOURCE_TARBALL='https://python.org/ftp/python/3.6.0/Python-3.6.0.tgz'
curl -L $SOURCE_TARBALL | tar xz
mv Python-3.6.0 src
cd src
./configure --prefix=$OUT_PREFIX --with-ensurepip=no
make
make install
ln $OUT_PREFIX/bin/python3 $OUT_PREFIX/bin/python
+1
View File
@@ -0,0 +1 @@
psycopg2
+1
View File
@@ -0,0 +1 @@
requests
+1
View File
@@ -0,0 +1 @@
python-2.7.13
+1
View File
@@ -0,0 +1 @@
requests
+1
View File
@@ -0,0 +1 @@
python-3.6.0
+1
View File
@@ -0,0 +1 @@
requests
+114
View File
@@ -0,0 +1,114 @@
Maya: Datetime for Humans™
==========================
.. image:: https://img.shields.io/pypi/v/maya.svg
:target: https://pypi.python.org/pypi/maya
.. image:: https://travis-ci.org/kennethreitz/maya.svg?branch=master
:target: https://travis-ci.org/kennethreitz/maya
.. image:: https://img.shields.io/badge/SayThanks.io-☼-1EAEDB.svg
:target: https://saythanks.io/to/kennethreitz
Datetimes are very frustrating to work with in Python, especially when dealing
with different locales on different systems. This library exists to make the
simple things **much** easier, while admitting that time is an illusion
(timezones doubly so).
Datetimes should be interacted with via an API written for humans.
Maya is mostly built around the headaches and use-cases around parsing datetime data from websites.
☤ Basic Usage of Maya
---------------------
Behold, datetimes for humans!
.. code-block:: pycon
>>> now = maya.now()
<MayaDT epoch=1481850660.9>
>>> tomorrow = maya.when('tomorrow')
<MayaDT epoch=1481919067.23>
>>> tomorrow.slang_date()
'tomorrow'
>>> tomorrow.slang_time()
'23 hours from now'
>>> tomorrow.iso8601()
'2016-12-16T15:11:30.263350Z'
>>> tomorrow.rfc2822()
'Fri, 16 Dec 2016 20:11:30 -0000'
>>> tomorrow.datetime()
datetime.datetime(2016, 12, 16, 15, 11, 30, 263350, tzinfo=<UTC>)
# Automatically parse datetime strings and generate naive datetimes.
>>> scraped = '2016-12-16 18:23:45.423992+00:00'
>>> maya.parse(scraped).datetime(to_timezone='US/Eastern', naive=True)
datetime.datetime(2016, 12, 16, 13, 23, 45, 423992)
>>> rand_day = maya.when('2011-02-07', timezone='US/Eastern')
<MayaDT epoch=1297036800.0>
# Note how this is the 6th, not the 7th.
>>> rand_day.day
6
# Always.
>>> rand_day.timezone
UTC
☤ Why is this useful?
---------------------
- All timezone algebra will behave identically on all machines, regardless of system locale.
- Complete symmetric import and export of both ISO 8601 and RFC 2822 datetime stamps.
- Fantastic parsing of both dates written for/by humans and machines (``maya.when()`` vs ``maya.parse()``).
- Support for human slang, both import and export (e.g. `an hour ago`).
- Datetimes can very easily be generated, with or without tzinfo attached.
- This library is based around epoch time, but dates before Jan 1 1970 are indeed supported, via negative integers.
- Maya never panics, and always carries a towel.
☤ What about Delorean, Arrow, & Pendulum?
-----------------------------------------
Arrow, for example, is a fantastic library, but isn't what I wanted in a datetime library. In many ways, it's better than Maya for certain things. In some ways, in my opinion, it's not.
I simply desire a sane API for datetimes that made sense to me for all the things I'd ever want to do—especially when dealing with timezone algebra. Arrow doesn't do all of the things I need (but it does a lot more!). Maya does do exactly what I need.
I think these projects complement each-other, personally. Maya is great for parsing websites. For example- Arrow supports floors and ceilings and spans of dates, which Maya does not at all.
☤ Installing Maya
-----------------
Installation is easy, with pip::
$ pip install maya
✨🍰✨
☤ Like it?
----------
`Say Thanks <https://saythanks.io/to/kennethreitz>`_!
How to Contribute
-----------------
#. Check for open issues or open a fresh issue to start a discussion around a feature idea or a bug.
#. Fork `the repository`_ on GitHub to start making your changes to the **master** branch (or branch off of it).
#. Write a test which shows that the bug was fixed or that the feature works as expected.
#. Send a pull request and bug the maintainer until it gets merged and published. :) Make sure to add yourself to AUTHORS_.
.. _`the repository`: http://github.com/kennethreitz/maya
.. _AUTHORS: https://github.com/kennethreitz/maya/blob/master/AUTHORS.rst
+273
View File
@@ -0,0 +1,273 @@
# ___ __ ___ _ _ ___
# || \/ | ||=|| \\// ||=||
# || | || || // || ||
# Ignore warnings for yaml usage.
import warnings
import ruamel.yaml
warnings.simplefilter('ignore', ruamel.yaml.error.UnsafeLoaderWarning)
import email.utils
import time
from datetime import datetime as Datetime
import pytz
import humanize
import dateparser
import iso8601
import dateutil.parser
from tzlocal import get_localzone
_EPOCH_START = (1970, 1, 1)
def validate_class_type_arguments(operator):
"""
Decorator to validate all the arguments to function
are of the type of calling class
"""
def inner(function):
def wrapper(self, *args, **kwargs):
for arg in args + tuple(kwargs.values()):
if not isinstance(arg, self.__class__):
raise TypeError('unorderable types: {}() {} {}()'.format(
type(self).__name__, operator, type(arg).__name__))
return function(self, *args, **kwargs)
return wrapper
return inner
class MayaDT(object):
"""The Maya Datetime object."""
def __init__(self, epoch):
super(MayaDT, self).__init__()
self._epoch = epoch
def __repr__(self):
return '<MayaDT epoch={}>'.format(self._epoch)
def __str__(self):
return self.rfc2822()
def __format__(self, *args, **kwargs):
"""Return's the datetime's format"""
return format(self.datetime(), *args, **kwargs)
@validate_class_type_arguments('==')
def __eq__(self, maya_dt):
return self._epoch == maya_dt._epoch
@validate_class_type_arguments('!=')
def __ne__(self, maya_dt):
return self._epoch != maya_dt._epoch
@validate_class_type_arguments('<')
def __lt__(self, maya_dt):
return self._epoch < maya_dt._epoch
@validate_class_type_arguments('<=')
def __le__(self, maya_dt):
return self._epoch <= maya_dt._epoch
@validate_class_type_arguments('>')
def __gt__(self, maya_dt):
return self._epoch > maya_dt._epoch
@validate_class_type_arguments('>=')
def __ge__(self, maya_dt):
return self._epoch >= maya_dt._epoch
# Timezone Crap
# -------------
@property
def timezone(self):
"""Returns the UTC tzinfo name. It's always UTC. Always."""
return 'UTC'
@property
def _tz(self):
"""Returns the UTC tzinfo object."""
return pytz.timezone(self.timezone)
@property
def local_timezone(self):
"""Returns the name of the local timezone, for informational purposes."""
return self._local_tz.zone
@property
def _local_tz(self):
"""Returns the local timezone."""
return get_localzone()
@staticmethod
def __dt_to_epoch(dt):
"""Converts a datetime into an epoch."""
# Assume UTC if no datetime is provided.
if dt.tzinfo is None:
dt = dt.replace(tzinfo=pytz.utc)
epoch_start = Datetime(*_EPOCH_START, tzinfo=pytz.timezone('UTC'))
return (dt - epoch_start).total_seconds()
# Importers
# ---------
@classmethod
def from_datetime(klass, dt):
"""Returns MayaDT instance from datetime."""
return klass(klass.__dt_to_epoch(dt))
@classmethod
def from_iso8601(klass, string):
"""Returns MayaDT instance from iso8601 string."""
dt = iso8601.parse_date(string)
return klass.from_datetime(dt)
@staticmethod
def from_rfc2822(string):
"""Returns MayaDT instance from rfc2822 string."""
return parse(string)
# Exporters
# ---------
def datetime(self, to_timezone=None, naive=False):
"""Returns a timezone-aware datetime...
Defaulting to UTC (as it should).
Keyword Arguments:
to_timezone {string} -- timezone to convert to (default: None/UTC)
naive {boolean} -- if True, the tzinfo is simply dropped (default: False)
"""
if to_timezone:
dt = self.datetime().astimezone(pytz.timezone(to_timezone))
else:
dt = Datetime.utcfromtimestamp(self._epoch)
dt.replace(tzinfo=self._tz)
# Strip the timezone info if requested to do so.
if naive:
return dt.replace(tzinfo=None)
else:
if dt.tzinfo is None:
dt = dt.replace(tzinfo=self._tz)
return dt
def iso8601(self):
"""Returns an ISO 8601 representation of the MayaDT."""
# Get a timezone-naive datetime.
dt = self.datetime(naive=True)
return '{}Z'.format(dt.isoformat())
def rfc2822(self):
"""Returns an RFC 2822 representation of the MayaDT."""
return email.utils.formatdate(self.epoch, usegmt=True)
# Properties
# ----------
@property
def year(self):
return self.datetime().year
@property
def month(self):
return self.datetime().month
@property
def day(self):
return self.datetime().day
@property
def week(self):
return self.datetime().isocalendar()[1]
@property
def weekday(self):
"""Return the day of the week as an integer. Monday is 1 and Sunday is 7"""
return self.datetime().isoweekday()
@property
def hour(self):
return self.datetime().hour
@property
def minute(self):
return self.datetime().minute
@property
def second(self):
return self.datetime().second
@property
def microsecond(self):
return self.datetime().microsecond
@property
def epoch(self):
return self._epoch
# Human Slang Extras
# ------------------
def slang_date(self):
""""Returns human slang representation of date."""
dt = self.datetime(naive=True, to_timezone=self.local_timezone)
return humanize.naturaldate(dt)
def slang_time(self):
""""Returns human slang representation of time."""
dt = self.datetime(naive=True, to_timezone=self.local_timezone)
return humanize.naturaltime(dt)
def now():
"""Returns a MayaDT instance for this exact moment."""
epoch = time.time()
return MayaDT(epoch=epoch)
def when(string, timezone='UTC'):
""""Returns a MayaDT instance for the human moment specified.
Powered by dateparser. Useful for scraping websites.
Examples:
'next week', 'now', 'tomorrow', '300 years ago', 'August 14, 2015'
Keyword Arguments:
string -- string to be parsed
timezone -- timezone referenced from (default: 'UTC')
"""
dt = dateparser.parse(string, settings={'TIMEZONE': timezone, 'RETURN_AS_TIMEZONE_AWARE': True, 'TO_TIMEZONE': 'UTC'})
if dt is None:
raise ValueError('invalid datetime input specified.')
return MayaDT.from_datetime(dt)
def parse(string, day_first=False):
""""Returns a MayaDT instance for the machine-produced moment specified.
Powered by dateutil. Accepts most known formats. Useful for working with data.
Keyword Arguments:
string -- string to be parsed
day_first -- if true, the first value (e.g. 01/05/2016) is parsed as day (default: False)
"""
dt = dateutil.parser.parse(string, dayfirst=day_first)
return MayaDT.from_datetime(dt)
+51
View File
@@ -0,0 +1,51 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import sys
import codecs
from setuptools import setup
try:
# Python 3
from os import dirname
except ImportError:
# Python 2
from os.path import dirname
here = os.path.abspath(dirname(__file__))
with codecs.open(os.path.join(here, 'README.rst'), encoding='utf-8') as f:
long_description = '\n' + f.read()
if sys.argv[-1] == "publish":
os.system("python setup.py sdist bdist_wheel upload")
sys.exit()
required = [
'humanize',
'pytz',
'dateparser',
'iso8601',
'python-dateutil',
'ruamel.yaml',
'tzlocal'
]
setup(
name='maya',
version='0.1.6',
description='Datetimes for Humans.',
long_description=long_description,
author='Kenneth Reitz',
author_email='me@kennethreitz.com',
url='https://github.com/kennethreitz/maya',
py_modules=['maya'],
install_requires=required,
license='MIT',
classifiers=(
),
)
Executable
+99
View File
@@ -0,0 +1,99 @@
#!/usr/bin/env bash
testNoRequirements() {
compile "no-requirements"
assertCapturedError
}
testSetupPy() {
compile "setup-py"
assertCaptured "maya"
assertCapturedSuccess
}
testStandardRequirements() {
compile "requirements-standard"
assertCaptured "requests"
assertCapturedSuccess
}
testPsycopg2() {
compile "psycopg2"
assertCaptured "psycopg2"
assertCapturedSuccess
}
testPython2() {
compile "python2"
assertCaptured "python-2.7.13"
assertCapturedSuccess
}
testPython3() {
compile "python3"
assertCaptured "python-3.6.0"
assertCapturedSuccess
}
pushd $(dirname 0) >/dev/null
popd >/dev/null
source $(pwd)/test/utils
mktmpdir() {
dir=$(mktemp -t testXXXXX)
rm -rf $dir
mkdir $dir
echo $dir
}
detect() {
capture $(pwd)/bin/detect $(pwd)/test/fixtures/$1
}
compile_dir=""
default_process_types_cleanup() {
file="/tmp/default_process_types"
if [ -f "$file" ]; then
rm "$file"
fi
}
compile() {
default_process_types_cleanup
bp_dir=$(mktmpdir)
compile_dir=$(mktmpdir)
cp -a $(pwd)/* ${bp_dir}
cp -a ${bp_dir}/test/fixtures/$1/. ${compile_dir}
capture ${bp_dir}/bin/compile ${compile_dir} ${2:-$(mktmpdir)} $3
}
compileDir() {
default_process_types_cleanup
local bp_dir=$(mktmpdir)
local compile_dir=${1:-$(mktmpdir)}
local cache_dir=${2:-$(mktmpdir)}
local env_dir=$3
cp -a $(pwd)/* ${bp_dir}
capture ${bp_dir}/bin/compile ${compile_dir} ${cache_dir} ${env_dir}
}
release() {
bp_dir=$(mktmpdir)
cp -a $(pwd)/* ${bp_dir}
capture ${bp_dir}/bin/release ${bp_dir}/test/fixtures/$1
}
assertFile() {
assertEquals "$1" "$(cat ${compile_dir}/$2)"
}
source $(pwd)/test/shunit2
Executable
+1048
View File
File diff suppressed because it is too large Load Diff
+195
View File
@@ -0,0 +1,195 @@
#!/bin/sh
# taken from
# https://github.com/ryanbrainard/heroku-buildpack-testrunner/blob/master/lib/test_utils.sh
oneTimeSetUp()
{
TEST_SUITE_CACHE="$(mktemp -d ${SHUNIT_TMPDIR}/test_suite_cache.XXXX)"
}
oneTimeTearDown()
{
rm -rf ${TEST_SUITE_CACHE}
}
setUp()
{
OUTPUT_DIR="$(mktemp -d ${SHUNIT_TMPDIR}/output.XXXX)"
STD_OUT="${OUTPUT_DIR}/stdout"
STD_ERR="${OUTPUT_DIR}/stderr"
BUILD_DIR="${OUTPUT_DIR}/build"
CACHE_DIR="${OUTPUT_DIR}/cache"
mkdir -p ${OUTPUT_DIR}
mkdir -p ${BUILD_DIR}
mkdir -p ${CACHE_DIR}
}
tearDown()
{
rm -rf ${OUTPUT_DIR}
}
capture()
{
resetCapture
LAST_COMMAND="$@"
$@ >${STD_OUT} 2>${STD_ERR}
RETURN=$?
rtrn=${RETURN} # deprecated
}
resetCapture()
{
if [ -f ${STD_OUT} ]; then
rm ${STD_OUT}
fi
if [ -f ${STD_ERR} ]; then
rm ${STD_ERR}
fi
unset LAST_COMMAND
unset RETURN
unset rtrn # deprecated
}
detect()
{
capture ${BUILDPACK_HOME}/bin/detect ${BUILD_DIR}
}
compile()
{
capture ${BUILDPACK_HOME}/bin/compile ${BUILD_DIR} ${CACHE_DIR}
}
release()
{
capture ${BUILDPACK_HOME}/bin/release ${BUILD_DIR}
}
assertCapturedEquals()
{
assertEquals "$@" "$(cat ${STD_OUT})"
}
assertCapturedNotEquals()
{
assertNotEquals "$@" "$(cat ${STD_OUT})"
}
assertCaptured()
{
assertFileContains "$@" "${STD_OUT}"
}
assertNotCaptured()
{
assertFileNotContains "$@" "${STD_OUT}"
}
assertCapturedSuccess()
{
assertEquals "Expected captured exit code to be 0; was <${RETURN}>" "0" "${RETURN}"
assertEquals "Expected STD_ERR to be empty; was <$(cat ${STD_ERR})>" "" "$(cat ${STD_ERR})"
}
# assertCapturedError [[expectedErrorCode] expectedErrorMsg]
assertCapturedError()
{
if [ $# -gt 1 ]; then
local expectedErrorCode=${1}
shift
fi
local expectedErrorMsg=${1:-""}
if [ -z ${expectedErrorCode} ]; then
assertTrue "Expected captured exit code to be greater than 0; was <${RETURN}>" "[ ${RETURN} -gt 0 ]"
else
assertTrue "Expected captured exit code to be <${expectedErrorCode}>; was <${RETURN}>" "[ ${RETURN} -eq ${expectedErrorCode} ]"
fi
if [ "${expectedErrorMsg}" != "" ]; then
assertFileContains "Expected STD_ERR to contain error <${expectedErrorMsg}>" "${expectedErrorMsg}" "${STD_ERR}"
fi
}
_assertContains()
{
if [ 5 -eq $# ]; then
local msg=$1
shift
elif [ ! 4 -eq $# ]; then
fail "Expected 4 or 5 parameters; Receieved $# parameters"
fi
local needle=$1
local haystack=$2
local expectation=$3
local haystack_type=$4
case "${haystack_type}" in
"file") grep -q -F -e "${needle}" ${haystack} ;;
"text") echo "${haystack}" | grep -q -F -e "${needle}" ;;
esac
if [ "${expectation}" != "$?" ]; then
case "${expectation}" in
0) default_msg="Expected <${haystack}> to contain <${needle}>" ;;
1) default_msg="Did not expect <${haystack}> to contain <${needle}>" ;;
esac
fail "${msg:-${default_msg}}"
fi
}
debug()
{
cat $STD_OUT
}
assertContains()
{
_assertContains "$@" 0 "text"
}
assertNotContains()
{
_assertContains "$@" 1 "text"
}
assertFileContains()
{
_assertContains "$@" 0 "file"
}
assertFileNotContains()
{
_assertContains "$@" 1 "file"
}
command_exists () {
type "$1" > /dev/null 2>&1 ;
}
assertFileMD5()
{
expectedHash=$1
filename=$2
if command_exists "md5sum"; then
md5_cmd="md5sum ${filename}"
expected_md5_cmd_output="${expectedHash} ${filename}"
elif command_exists "md5"; then
md5_cmd="md5 ${filename}"
expected_md5_cmd_output="MD5 (${filename}) = ${expectedHash}"
else
fail "no suitable MD5 hashing command found on this system"
fi
assertEquals "${expected_md5_cmd_output}" "`${md5_cmd}`"
}
+11 -5
View File
@@ -1,32 +1,38 @@
if [[ "${WEB_CONCURRENCY:-}" == 0* ]]; then
# another buildpack set a default value, with leading zero
unset WEB_CONCURRENCY
fi
case $(ulimit -u) in case $(ulimit -u) in
# Automatic configuration for Gunicorn's Workers setting. # Automatic configuration for Gunicorn's Workers setting.
# Leading zero padding so a subsequent buildpack can figure out that we set a value, and not the user
# Standard-1X (+Free, +Hobby) Dyno # Standard-1X (+Free, +Hobby) Dyno
256) 256)
export DYNO_RAM=512 export DYNO_RAM=512
export WEB_CONCURRENCY=${WEB_CONCURRENCY:-2} export WEB_CONCURRENCY=${WEB_CONCURRENCY:-02}
;; ;;
# Standard-2X Dyno # Standard-2X Dyno
512) 512)
export DYNO_RAM=1024 export DYNO_RAM=1024
export WEB_CONCURRENCY=${WEB_CONCURRENCY:-4} export WEB_CONCURRENCY=${WEB_CONCURRENCY:-04}
;; ;;
# Performance-M Dyno # Performance-M Dyno
16384) 16384)
export DYNO_RAM=2560 export DYNO_RAM=2560
export WEB_CONCURRENCY=${WEB_CONCURRENCY:-8} export WEB_CONCURRENCY=${WEB_CONCURRENCY:-08}
;; ;;
# Performance-L Dyno # Performance-L Dyno
32768) 32768)
export DYNO_RAM=6656 export DYNO_RAM=6656
export WEB_CONCURRENCY=${WEB_CONCURRENCY:-11} export WEB_CONCURRENCY=${WEB_CONCURRENCY:-011}
;; ;;
esac esac
# Automatic configuration for Gunicorn's ForwardedAllowIPS setting. # Automatic configuration for Gunicorn's ForwardedAllowIPS setting.
export FORWARDED_ALLOW_IPS='*' export FORWARDED_ALLOW_IPS='*'
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.