diff --git a/server/.env.example b/server/.env.example index 341312cb1..778fac167 100644 --- a/server/.env.example +++ b/server/.env.example @@ -2,6 +2,7 @@ ############################### API SETTINGS ############################# # Server +HOST=0.0.0.0 PORT=5000 DEBUG=0 ACCESS_LOG=1 diff --git a/server/.gitignore b/server/.gitignore index 07ad871a6..f70007d4b 100644 --- a/server/.gitignore +++ b/server/.gitignore @@ -1,6 +1,7 @@ -.env +*.env /api/__tmp__ /jmeter/out __pycache__ +.pytest_cache diff --git a/server/README.md b/server/README.md index a5ba3bb6e..4266cf12e 100644 --- a/server/README.md +++ b/server/README.md @@ -1,35 +1,42 @@ -## Getting Started +# Getting Started -### TL;DR - - install docker and docker compose on your machine - - run `chmod +x install.sh && ./install.sh` from this directory - - put a [Socrata](https://dev.socrata.com/) api token in your `.env` file - - run `docker-compose run api python bin/db_seed.py --years 2019,2020` +## TL;DR + +- install docker and docker compose on your machine +- run `chmod +x install.sh && ./install.sh` from this directory +- put a [Socrata](https://dev.socrata.com/) API token in your `.env` file +- run `docker-compose run api python bin/db_seed.py --years 2019,2020` ### Step 1: install docker and docker-compose + Docker and Docker-Compose are the only required dependencies for running the server. You can find installation instructions [here](https://docs.docker.com/compose/install/) for Docker and [here](https://docs.docker.com/compose/install/) for Docker-Compose. Once you're done, you can check that everything is working: -``` + +```bash docker --version # confirms docker is installed docker-compose --version # confirms docker-compose is installed docker info # confirms the docker daemon is running ``` ### Step 2: run the install script + With docker running on your machine, `cd` into this directory and run: -``` + +```bash chmod +x install.sh && ./install.sh ``` -This will download/build a bunch of docker images, create your `.env` file, set up your database, and then fire everything up. If all goes well, at the end you should have running api server backed by Postgres and Redis. You can then tour the running services by hitting these URLs in a browser: -- http://localhost:5000 -- the api -- should say "you hit the index". This means the api is running. -- http://localhost:8080 -- a postgres GUI. Login with the following: + +This will download/build a bunch of docker images, create your `.env` file, set up your database, and then fire everything up. If all goes well, at the end you should have running API server backed by Postgres and Redis. You can then tour the running services by hitting these URLs in a browser: + +- http://localhost:5000 -- the API -- should say "you hit the index". This means the API is running. +- http://localhost:8080 -- a Postgres GUI. Login with the following: - System: **PostgreSQL** - Server: **db** - Username: **311_user** - Password: **311_pass** - Database: **311_db** -- http://localhost:5001 -- a redis GUI. Login with the following: +- http://localhost:5001 -- a Redis GUI. Login with the following: - Host: **redis** - Port: **6379** - Database ID: **0** @@ -37,35 +44,44 @@ This will download/build a bunch of docker images, create your `.env` file, set You can shut down all the services by hitting `Ctrl-C`. And run `docker-compose up` to bring everything back up again. ### Step 3: seed your database + Right now the server is functional and all endpoints should be working. But for most purposes you'll need some data in your database. The data comes from [Socrata](https://dev.socrata.com/), a public api that hosts many datasets for LA and other cities. To add data, you'll need to get a Socrata token and run one more command. - #### 3a: add a Socrata token to your .env file (possible optional) + Socrata threatens to throttle you if you don't have an api token. We're not sure they actually do that, but the api does seem to run more slowly without a token. So get a token from another team member, or [register](https://opendata.socrata.com/login) with Socrata and they'll give you one. Then add it to the Socrata section in your `.env` file: -``` + +```bash SOCRATA_TOKEN=thetoken ``` + - #### 3b: run the seed script + It takes a while to seed the database, so we recommend starting with 2 years of data from Socrata. Run the following command to get data for 2019 and 2020, which is plenty for most dev purposes. ETA **20 to 30 minutes**. (If you've still got the backend services running, you can run this command in a separate terminal window.) -``` + +```bash docker-compose run api python bin/db_seed.py --years 2019,2020 ``` + If you decide later that you need more data, just run the command again with the year(s) you want to add. Socrata goes back to 2015. (NOTE: run the above command with `--help` instead of `--years` for more info on the options. And if you ever want to reset your database and start over, run `docker-compose run api python bin/db_reset.py`.) - ## Development ### Optional Dependencies - - #### Postman +#### Postman + [Postman](https://www.postman.com/) is an api-development tool that lets you save api requests so you can run them over and over without having to remember what all the parameters are (or use the awkward syntax of `curl`). You can also group api calls together in collections, and run all of the api calls in a collection at once -- which is a great way to test the entire api. If you'd like to use it, see the README in `/server/postman`, which explains how to set it up with a collection that contains pre-defined api calls for all of our endpoints. - - #### Jmeter -[Jmeter](https://jmeter.apache.org/) is a performance-focused api testing tool. It produces reports that show how the api performs when multiple users are using the app simultaneously. For more info, see the README in `/server/jmeter`. +#### JMeter + +[JMeter](https://jmeter.apache.org/) is a performance-focused api testing tool. It produces reports that show how the api performs when multiple users are using the app simultaneously. For more info, see the README in `/server/jmeter`. ### Useful commands -``` + +```bash docker-compose up # start the backend services docker-compose up --build # start the backend services after rebuilding containers @@ -75,7 +91,8 @@ docker-compose run api pytest # run unit tests against python code ``` ### Using the python interpreter -``` + +```bash docker-compose run api bash cd src python @@ -93,7 +110,9 @@ Type "help", "copyright", "credits" or "license" for more information. ``` ## Uninstall + Run this command to remove all docker containers, images, volumes, and networks that are specific to this project. It will leave in place generic docker assets (like the `postgres` and `python` images) that you may be using for other purposes. -``` + +```bash docker-compose down --rmi local --volumes ``` diff --git a/server/api/Pipfile b/server/api/Pipfile new file mode 100644 index 000000000..8764fdb15 --- /dev/null +++ b/server/api/Pipfile @@ -0,0 +1,61 @@ +[[source]] +name = "pypi" +url = "https://pypi.org/simple" +verify_ssl = true + +[dev-packages] + +[packages] +aiofiles = "==0.4.0" +attrs = "==19.3.0" +certifi = "==2019.11.28" +chardet = "==3.0.4" +entrypoints = "==0.3" +flake8 = "==3.7.9" +h11 = "==0.8.1" +h2 = "==3.1.1" +hpack = "==3.0.0" +httpcore = "==0.3.0" +httptools = "==0.0.13" +hyperframe = "==5.2.0" +idna = "==2.9" +importlib-metadata = "==1.4.0" +mccabe = "==0.6.1" +more-itertools = "==8.1.0" +multidict = "==4.5.2" +numpy = "==1.18.1" +pandas = "==1.0.1" +pluggy = "==0.13.1" +psycopg2-binary = "==2.8.4" +py = "==1.8.1" +pycodestyle = "==2.5.0" +pyflakes = "==2.1.1" +pyparsing = "==2.4.6" +pysupercluster = "==0.7.6" +pytest = "==5.3.3" +python-dateutil = "==2.8.1" +python-dotenv = "==0.13.0" +python-http-client = "==3.2.7" +pytz = "==2019.3" +redis = "==3.5.0" +requests = "==2.23.0" +requests-async = "==0.5.0" +rfc3986 = "==1.3.2" +sanic = "==19.9.0" +sendgrid = "==6.3.1" +six = "==1.14.0" +sodapy = "==2.0.0" +tabulate = "==0.8.7" +ujson = "==1.35" +urllib3 = "==1.25.8" +uvloop = "==0.14.0" +wcwidth = "==0.1.8" +websockets = "==8.1" +zipp = "==1.0.0" +sanic_compress = "==0.1.1" +Sanic-Cors = "==0.10.0.post3" +Sanic-Plugins-Framework = "==0.9.2" +SQLAlchemy = "==1.3.13" + +[requires] +python_version = "3.7" diff --git a/server/api/Pipfile.lock b/server/api/Pipfile.lock new file mode 100644 index 000000000..e7dd0c6eb --- /dev/null +++ b/server/api/Pipfile.lock @@ -0,0 +1,535 @@ +{ + "_meta": { + "hash": { + "sha256": "23a8760158785c5909e4d5a9f738b033775a80af35ffb4a6d2d287415ac0816b" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "3.7" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "aiofiles": { + "hashes": [ + "sha256:021ea0ba314a86027c166ecc4b4c07f2d40fc0f4b3a950d1868a0f2571c2bbee", + "sha256:1e644c2573f953664368de28d2aa4c89dfd64550429d0c27c4680ccd3aa4985d" + ], + "index": "pypi", + "version": "==0.4.0" + }, + "attrs": { + "hashes": [ + "sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c", + "sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72" + ], + "index": "pypi", + "version": "==19.3.0" + }, + "certifi": { + "hashes": [ + "sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3", + "sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f" + ], + "index": "pypi", + "version": "==2019.11.28" + }, + "chardet": { + "hashes": [ + "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", + "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" + ], + "index": "pypi", + "version": "==3.0.4" + }, + "entrypoints": { + "hashes": [ + "sha256:589f874b313739ad35be6e0cd7efde2a4e9b6fea91edcc34e58ecbb8dbe56d19", + "sha256:c70dd71abe5a8c85e55e12c19bd91ccfeec11a6e99044204511f9ed547d48451" + ], + "index": "pypi", + "version": "==0.3" + }, + "flake8": { + "hashes": [ + "sha256:45681a117ecc81e870cbf1262835ae4af5e7a8b08e40b944a8a6e6b895914cfb", + "sha256:49356e766643ad15072a789a20915d3c91dc89fd313ccd71802303fd67e4deca" + ], + "index": "pypi", + "version": "==3.7.9" + }, + "h11": { + "hashes": [ + "sha256:acca6a44cb52a32ab442b1779adf0875c443c689e9e028f8d831a3769f9c5208", + "sha256:f2b1ca39bfed357d1f19ac732913d5f9faa54a5062eca7d2ec3a916cfb7ae4c7" + ], + "index": "pypi", + "version": "==0.8.1" + }, + "h2": { + "hashes": [ + "sha256:ac377fcf586314ef3177bfd90c12c7826ab0840edeb03f0f24f511858326049e", + "sha256:b8a32bd282594424c0ac55845377eea13fa54fe4a8db012f3a198ed923dc3ab4" + ], + "index": "pypi", + "version": "==3.1.1" + }, + "hpack": { + "hashes": [ + "sha256:0edd79eda27a53ba5be2dfabf3b15780928a0dff6eb0c60a3d6767720e970c89", + "sha256:8eec9c1f4bfae3408a3f30500261f7e6a65912dc138526ea054f9ad98892e9d2" + ], + "index": "pypi", + "version": "==3.0.0" + }, + "httpcore": { + "hashes": [ + "sha256:96f910b528d47b683242ec207050c7bbaa99cd1b9a07f78ea80cf61e55556b58" + ], + "index": "pypi", + "version": "==0.3.0" + }, + "httptools": { + "hashes": [ + "sha256:e00cbd7ba01ff748e494248183abc6e153f49181169d8a3d41bb49132ca01dfc" + ], + "index": "pypi", + "version": "==0.0.13" + }, + "hyperframe": { + "hashes": [ + "sha256:5187962cb16dcc078f23cb5a4b110098d546c3f41ff2d4038a9896893bbd0b40", + "sha256:a9f5c17f2cc3c719b917c4f33ed1c61bd1f8dfac4b1bd23b7c80b3400971b41f" + ], + "index": "pypi", + "version": "==5.2.0" + }, + "idna": { + "hashes": [ + "sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb", + "sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa" + ], + "index": "pypi", + "version": "==2.9" + }, + "importlib-metadata": { + "hashes": [ + "sha256:bdd9b7c397c273bcc9a11d6629a38487cd07154fa255a467bf704cd2c258e359", + "sha256:f17c015735e1a88296994c0697ecea7e11db24290941983b08c9feb30921e6d8" + ], + "index": "pypi", + "version": "==1.4.0" + }, + "mccabe": { + "hashes": [ + "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", + "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f" + ], + "index": "pypi", + "version": "==0.6.1" + }, + "more-itertools": { + "hashes": [ + "sha256:1a2a32c72400d365000412fe08eb4a24ebee89997c18d3d147544f70f5403b39", + "sha256:c468adec578380b6281a114cb8a5db34eb1116277da92d7c46f904f0b52d3288" + ], + "index": "pypi", + "version": "==8.1.0" + }, + "multidict": { + "hashes": [ + "sha256:024b8129695a952ebd93373e45b5d341dbb87c17ce49637b34000093f243dd4f", + "sha256:041e9442b11409be5e4fc8b6a97e4bcead758ab1e11768d1e69160bdde18acc3", + "sha256:045b4dd0e5f6121e6f314d81759abd2c257db4634260abcfe0d3f7083c4908ef", + "sha256:047c0a04e382ef8bd74b0de01407e8d8632d7d1b4db6f2561106af812a68741b", + "sha256:068167c2d7bbeebd359665ac4fff756be5ffac9cda02375b5c5a7c4777038e73", + "sha256:148ff60e0fffa2f5fad2eb25aae7bef23d8f3b8bdaf947a65cdbe84a978092bc", + "sha256:1d1c77013a259971a72ddaa83b9f42c80a93ff12df6a4723be99d858fa30bee3", + "sha256:1d48bc124a6b7a55006d97917f695effa9725d05abe8ee78fd60d6588b8344cd", + "sha256:31dfa2fc323097f8ad7acd41aa38d7c614dd1960ac6681745b6da124093dc351", + "sha256:34f82db7f80c49f38b032c5abb605c458bac997a6c3142e0d6c130be6fb2b941", + "sha256:3d5dd8e5998fb4ace04789d1d008e2bb532de501218519d70bb672c4c5a2fc5d", + "sha256:4a6ae52bd3ee41ee0f3acf4c60ceb3f44e0e3bc52ab7da1c2b2aa6703363a3d1", + "sha256:4b02a3b2a2f01d0490dd39321c74273fed0568568ea0e7ea23e02bd1fb10a10b", + "sha256:4b843f8e1dd6a3195679d9838eb4670222e8b8d01bc36c9894d6c3538316fa0a", + "sha256:5de53a28f40ef3c4fd57aeab6b590c2c663de87a5af76136ced519923d3efbb3", + "sha256:61b2b33ede821b94fa99ce0b09c9ece049c7067a33b279f343adfe35108a4ea7", + "sha256:6a3a9b0f45fd75dc05d8e93dc21b18fc1670135ec9544d1ad4acbcf6b86781d0", + "sha256:76ad8e4c69dadbb31bad17c16baee61c0d1a4a73bed2590b741b2e1a46d3edd0", + "sha256:7ba19b777dc00194d1b473180d4ca89a054dd18de27d0ee2e42a103ec9b7d014", + "sha256:7c1b7eab7a49aa96f3db1f716f0113a8a2e93c7375dd3d5d21c4941f1405c9c5", + "sha256:7fc0eee3046041387cbace9314926aa48b681202f8897f8bff3809967a049036", + "sha256:8ccd1c5fff1aa1427100ce188557fc31f1e0a383ad8ec42c559aabd4ff08802d", + "sha256:8e08dd76de80539d613654915a2f5196dbccc67448df291e69a88712ea21e24a", + "sha256:c18498c50c59263841862ea0501da9f2b3659c00db54abfbf823a80787fde8ce", + "sha256:c49db89d602c24928e68c0d510f4fcf8989d77defd01c973d6cbe27e684833b1", + "sha256:ce20044d0317649ddbb4e54dab3c1bcc7483c78c27d3f58ab3d0c7e6bc60d26a", + "sha256:d1071414dd06ca2eafa90c85a079169bfeb0e5f57fd0b45d44c092546fcd6fd9", + "sha256:d3be11ac43ab1a3e979dac80843b42226d5d3cccd3986f2e03152720a4297cd7", + "sha256:db603a1c235d110c860d5f39988ebc8218ee028f07a7cbc056ba6424372ca31b" + ], + "index": "pypi", + "version": "==4.5.2" + }, + "numpy": { + "hashes": [ + "sha256:1786a08236f2c92ae0e70423c45e1e62788ed33028f94ca99c4df03f5be6b3c6", + "sha256:17aa7a81fe7599a10f2b7d95856dc5cf84a4eefa45bc96123cbbc3ebc568994e", + "sha256:20b26aaa5b3da029942cdcce719b363dbe58696ad182aff0e5dcb1687ec946dc", + "sha256:2d75908ab3ced4223ccba595b48e538afa5ecc37405923d1fea6906d7c3a50bc", + "sha256:39d2c685af15d3ce682c99ce5925cc66efc824652e10990d2462dfe9b8918c6a", + "sha256:56bc8ded6fcd9adea90f65377438f9fea8c05fcf7c5ba766bef258d0da1554aa", + "sha256:590355aeade1a2eaba17617c19edccb7db8d78760175256e3cf94590a1a964f3", + "sha256:70a840a26f4e61defa7bdf811d7498a284ced303dfbc35acb7be12a39b2aa121", + "sha256:77c3bfe65d8560487052ad55c6998a04b654c2fbc36d546aef2b2e511e760971", + "sha256:9537eecf179f566fd1c160a2e912ca0b8e02d773af0a7a1120ad4f7507cd0d26", + "sha256:9acdf933c1fd263c513a2df3dceecea6f3ff4419d80bf238510976bf9bcb26cd", + "sha256:ae0975f42ab1f28364dcda3dde3cf6c1ddab3e1d4b2909da0cb0191fa9ca0480", + "sha256:b3af02ecc999c8003e538e60c89a2b37646b39b688d4e44d7373e11c2debabec", + "sha256:b6ff59cee96b454516e47e7721098e6ceebef435e3e21ac2d6c3b8b02628eb77", + "sha256:b765ed3930b92812aa698a455847141869ef755a87e099fddd4ccf9d81fffb57", + "sha256:c98c5ffd7d41611407a1103ae11c8b634ad6a43606eca3e2a5a269e5d6e8eb07", + "sha256:cf7eb6b1025d3e169989416b1adcd676624c2dbed9e3bcb7137f51bfc8cc2572", + "sha256:d92350c22b150c1cae7ebb0ee8b5670cc84848f6359cf6b5d8f86617098a9b73", + "sha256:e422c3152921cece8b6a2fb6b0b4d73b6579bd20ae075e7d15143e711f3ca2ca", + "sha256:e840f552a509e3380b0f0ec977e8124d0dc34dc0e68289ca28f4d7c1d0d79474", + "sha256:f3d0a94ad151870978fb93538e95411c83899c9dc63e6fb65542f769568ecfa5" + ], + "index": "pypi", + "version": "==1.18.1" + }, + "packaging": { + "hashes": [ + "sha256:4357f74f47b9c12db93624a82154e9b120fa8293699949152b22065d556079f8", + "sha256:998416ba6962ae7fbd6596850b80e17859a5753ba17c32284f67bfff33784181" + ], + "version": "==20.4" + }, + "pandas": { + "hashes": [ + "sha256:23e177d43e4bf68950b0f8788b6a2fef2f478f4ec94883acb627b9264522a98a", + "sha256:2530aea4fe46e8df7829c3f05e0a0f821c893885d53cb8ac9b89cc67c143448c", + "sha256:303827f0bb40ff610fbada5b12d50014811efcc37aaf6ef03202dc3054bfdda1", + "sha256:3b019e3ea9f5d0cfee0efabae2cfd3976874e90bcc3e97b29600e5a9b345ae3d", + "sha256:3c07765308f091d81b6735d4f2242bb43c332cc3461cae60543df6b10967fe27", + "sha256:5036d4009012a44aa3e50173e482b664c1fae36decd277c49e453463798eca4e", + "sha256:6f38969e2325056f9959efbe06c27aa2e94dd35382265ad0703681d993036052", + "sha256:74a470d349d52b9d00a2ba192ae1ee22155bb0a300fd1ccb2961006c3fa98ed3", + "sha256:7d77034e402165b947f43050a8a415aa3205abfed38d127ea66e57a2b7b5a9e0", + "sha256:7f9a509f6f11fa8b9313002ebdf6f690a7aa1dd91efd95d90185371a0d68220e", + "sha256:942b5d04762feb0e55b2ad97ce2b254a0ffdd344b56493b04a627266e24f2d82", + "sha256:a9fbe41663416bb70ed05f4e16c5f377519c0dc292ba9aa45f5356e37df03a38", + "sha256:d10e83866b48c0cdb83281f786564e2a2b51a7ae7b8a950c3442ad3c9e36b48c", + "sha256:e2140e1bbf9c46db9936ee70f4be6584d15ff8dc3dfff1da022d71227d53bad3" + ], + "index": "pypi", + "version": "==1.0.1" + }, + "pluggy": { + "hashes": [ + "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0", + "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d" + ], + "index": "pypi", + "version": "==0.13.1" + }, + "psycopg2-binary": { + "hashes": [ + "sha256:040234f8a4a8dfd692662a8308d78f63f31a97e1c42d2480e5e6810c48966a29", + "sha256:086f7e89ec85a6704db51f68f0dcae432eff9300809723a6e8782c41c2f48e03", + "sha256:18ca813fdb17bc1db73fe61b196b05dd1ca2165b884dd5ec5568877cabf9b039", + "sha256:19dc39616850342a2a6db70559af55b22955f86667b5f652f40c0e99253d9881", + "sha256:2166e770cb98f02ed5ee2b0b569d40db26788e0bf2ec3ae1a0d864ea6f1d8309", + "sha256:3a2522b1d9178575acee4adf8fd9f979f9c0449b00b4164bb63c3475ea6528ed", + "sha256:3aa773580f85a28ffdf6f862e59cb5a3cc7ef6885121f2de3fca8d6ada4dbf3b", + "sha256:3b5deaa3ee7180585a296af33e14c9b18c218d148e735c7accf78130765a47e3", + "sha256:407af6d7e46593415f216c7f56ba087a9a42bd6dc2ecb86028760aa45b802bd7", + "sha256:4c3c09fb674401f630626310bcaf6cd6285daf0d5e4c26d6e55ca26a2734e39b", + "sha256:4c6717962247445b4f9e21c962ea61d2e884fc17df5ddf5e35863b016f8a1f03", + "sha256:50446fae5681fc99f87e505d4e77c9407e683ab60c555ec302f9ac9bffa61103", + "sha256:5057669b6a66aa9ca118a2a860159f0ee3acf837eda937bdd2a64f3431361a2d", + "sha256:5dd90c5438b4f935c9d01fcbad3620253da89d19c1f5fca9158646407ed7df35", + "sha256:659c815b5b8e2a55193ede2795c1e2349b8011497310bb936da7d4745652823b", + "sha256:69b13fdf12878b10dc6003acc8d0abf3ad93e79813fd5f3812497c1c9fb9be49", + "sha256:7a1cb80e35e1ccea3e11a48afe65d38744a0e0bde88795cc56a4d05b6e4f9d70", + "sha256:7e6e3c52e6732c219c07bd97fff6c088f8df4dae3b79752ee3a817e6f32e177e", + "sha256:7f42a8490c4fe854325504ce7a6e4796b207960dabb2cbafe3c3959cb00d1d7e", + "sha256:84156313f258eafff716b2961644a4483a9be44a5d43551d554844d15d4d224e", + "sha256:8578d6b8192e4c805e85f187bc530d0f52ba86c39172e61cd51f68fddd648103", + "sha256:890167d5091279a27e2505ff0e1fb273f8c48c41d35c5b92adbf4af80e6b2ed6", + "sha256:98e10634792ac0e9e7a92a76b4991b44c2325d3e7798270a808407355e7bb0a1", + "sha256:9aadff9032e967865f9778485571e93908d27dab21d0fdfdec0ca779bb6f8ad9", + "sha256:9f24f383a298a0c0f9b3113b982e21751a8ecde6615494a3f1470eb4a9d70e9e", + "sha256:a73021b44813b5c84eda4a3af5826dd72356a900bac9bd9dd1f0f81ee1c22c2f", + "sha256:afd96845e12638d2c44d213d4810a08f4dc4a563f9a98204b7428e567014b1cd", + "sha256:b73ddf033d8cd4cc9dfed6324b1ad2a89ba52c410ef6877998422fcb9c23e3a8", + "sha256:b8f490f5fad1767a1331df1259763b3bad7d7af12a75b950c2843ba319b2415f", + "sha256:dbc5cd56fff1a6152ca59445178652756f4e509f672e49ccdf3d79c1043113a4", + "sha256:eac8a3499754790187bb00574ab980df13e754777d346f85e0ff6df929bcd964", + "sha256:eaed1c65f461a959284649e37b5051224f4db6ebdc84e40b5e65f2986f101a08" + ], + "index": "pypi", + "version": "==2.8.4" + }, + "py": { + "hashes": [ + "sha256:5e27081401262157467ad6e7f851b7aa402c5852dbcb3dae06768434de5752aa", + "sha256:c20fdd83a5dbc0af9efd622bee9a5564e278f6380fffcacc43ba6f43db2813b0" + ], + "index": "pypi", + "version": "==1.8.1" + }, + "pycodestyle": { + "hashes": [ + "sha256:95a2219d12372f05704562a14ec30bc76b05a5b297b21a5dfe3f6fac3491ae56", + "sha256:e40a936c9a450ad81df37f549d676d127b1b66000a6c500caa2b085bc0ca976c" + ], + "index": "pypi", + "version": "==2.5.0" + }, + "pyflakes": { + "hashes": [ + "sha256:17dbeb2e3f4d772725c777fabc446d5634d1038f234e77343108ce445ea69ce0", + "sha256:d976835886f8c5b31d47970ed689944a0262b5f3afa00a5a7b4dc81e5449f8a2" + ], + "index": "pypi", + "version": "==2.1.1" + }, + "pyparsing": { + "hashes": [ + "sha256:4c830582a84fb022400b85429791bc551f1f4871c33f23e44f353119e92f969f", + "sha256:c342dccb5250c08d45fd6f8b4a559613ca603b57498511740e65cd11a2e7dcec" + ], + "index": "pypi", + "version": "==2.4.6" + }, + "pysupercluster": { + "hashes": [ + "sha256:1e9739e9dad6126f346b5816dd6d9affc31d8482ef89fd30ff87f8412530726a" + ], + "index": "pypi", + "version": "==0.7.6" + }, + "pytest": { + "hashes": [ + "sha256:9f8d44f4722b3d06b41afaeb8d177cfbe0700f8351b1fc755dd27eedaa3eb9e0", + "sha256:f5d3d0e07333119fe7d4af4ce122362dc4053cdd34a71d2766290cf5369c64ad" + ], + "index": "pypi", + "version": "==5.3.3" + }, + "python-dateutil": { + "hashes": [ + "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c", + "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a" + ], + "index": "pypi", + "version": "==2.8.1" + }, + "python-dotenv": { + "hashes": [ + "sha256:25c0ff1a3e12f4bde8d592cc254ab075cfe734fc5dd989036716fd17ee7e5ec7", + "sha256:3b9909bc96b0edc6b01586e1eed05e71174ef4e04c71da5786370cebea53ad74" + ], + "index": "pypi", + "version": "==0.13.0" + }, + "python-http-client": { + "hashes": [ + "sha256:93d6a26b426e48b04e589c1f103e7c040193e4ccc379ea50cd6e12f94cca7c69" + ], + "index": "pypi", + "version": "==3.2.7" + }, + "pytz": { + "hashes": [ + "sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d", + "sha256:b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be" + ], + "index": "pypi", + "version": "==2019.3" + }, + "redis": { + "hashes": [ + "sha256:174101a3ce04560d716616290bb40e0a2af45d5844c8bd474c23fc5c52e7a46a", + "sha256:7378105cd8ea20c4edc49f028581e830c01ad5f00be851def0f4bc616a83cd89" + ], + "index": "pypi", + "version": "==3.5.0" + }, + "requests": { + "hashes": [ + "sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee", + "sha256:b3f43d496c6daba4493e7c431722aeb7dbc6288f52a6e04e7b6023b0247817e6" + ], + "index": "pypi", + "version": "==2.23.0" + }, + "requests-async": { + "hashes": [ + "sha256:8731420451383196ecf2fd96082bfc8ae5103ada90aba185888499d7784dde6f" + ], + "index": "pypi", + "version": "==0.5.0" + }, + "rfc3986": { + "hashes": [ + "sha256:0344d0bd428126ce554e7ca2b61787b6a28d2bbd19fc70ed2dd85efe31176405", + "sha256:df4eba676077cefb86450c8f60121b9ae04b94f65f85b69f3f731af0516b7b18" + ], + "index": "pypi", + "version": "==1.3.2" + }, + "sanic": { + "hashes": [ + "sha256:5e975a288d862a57db64349798b0180f2d6a4546ffd34dcd533cdda05467f06c", + "sha256:fdde669f97d5c7a8223b3ab671b9a2c9fe73dd3461195f9fb3951e87a312164d" + ], + "index": "pypi", + "version": "==19.9.0" + }, + "sanic-compress": { + "hashes": [ + "sha256:350123350caad62a6815f70b485fd98b6c3e94c1cdaefc4a192d3075d540522b" + ], + "index": "pypi", + "version": "==0.1.1" + }, + "sanic-cors": { + "hashes": [ + "sha256:abb0f8b17d2ecb12d62ecac42ca62bfed9b07fd00ffd83219ad23b99d4df3f23", + "sha256:b919d65643de810ed1ed15657b8bc75c310fa1ac8eb491d59deaa9404756b745" + ], + "index": "pypi", + "version": "==0.10.0.post3" + }, + "sanic-plugins-framework": { + "hashes": [ + "sha256:2949374e414a497a3b07b09800d3d0b3cdf24f3a1d3f08591488759099cb7f44", + "sha256:e63439f238f9e070649ee5c174d952b2fbc7e845259a3839e109b4bb2fbbb163" + ], + "index": "pypi", + "version": "==0.9.2" + }, + "sendgrid": { + "hashes": [ + "sha256:38c0853494c7bfbef64f33934c25bf98bb7648cf0e66a0cfb22410927e4ef4c7", + "sha256:838e1f7b0f84d56714be6a18ef66fbcf8fba0bda782eee35c47c04d7a16efde8" + ], + "index": "pypi", + "version": "==6.3.1" + }, + "six": { + "hashes": [ + "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a", + "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c" + ], + "index": "pypi", + "version": "==1.14.0" + }, + "sodapy": { + "hashes": [ + "sha256:93e357938473e0d35d5f32f5de4cbb749135ab18c95aebe138d945ceebb859b4", + "sha256:b02b4487adbaee915e180a2c1ea71355ed49c2d5e0762007b72d7044f5c908a3" + ], + "index": "pypi", + "version": "==2.0.0" + }, + "sqlalchemy": { + "hashes": [ + "sha256:64a7b71846db6423807e96820993fa12a03b89127d278290ca25c0b11ed7b4fb" + ], + "index": "pypi", + "version": "==1.3.13" + }, + "tabulate": { + "hashes": [ + "sha256:ac64cb76d53b1231d364babcd72abbb16855adac7de6665122f97b593f1eb2ba", + "sha256:db2723a20d04bcda8522165c73eea7c300eda74e0ce852d9022e0159d7895007" + ], + "index": "pypi", + "version": "==0.8.7" + }, + "ujson": { + "hashes": [ + "sha256:f66073e5506e91d204ab0c614a148d5aa938bdbf104751be66f8ad7a222f5f86" + ], + "index": "pypi", + "version": "==1.35" + }, + "urllib3": { + "hashes": [ + "sha256:2f3db8b19923a873b3e5256dc9c2dedfa883e33d87c690d9c7913e1f40673cdc", + "sha256:87716c2d2a7121198ebcb7ce7cccf6ce5e9ba539041cfbaeecfb641dc0bf6acc" + ], + "index": "pypi", + "version": "==1.25.8" + }, + "uvloop": { + "hashes": [ + "sha256:08b109f0213af392150e2fe6f81d33261bb5ce968a288eb698aad4f46eb711bd", + "sha256:123ac9c0c7dd71464f58f1b4ee0bbd81285d96cdda8bc3519281b8973e3a461e", + "sha256:4315d2ec3ca393dd5bc0b0089d23101276778c304d42faff5dc4579cb6caef09", + "sha256:4544dcf77d74f3a84f03dd6278174575c44c67d7165d4c42c71db3fdc3860726", + "sha256:afd5513c0ae414ec71d24f6f123614a80f3d27ca655a4fcf6cabe50994cc1891", + "sha256:b4f591aa4b3fa7f32fb51e2ee9fea1b495eb75b0b3c8d0ca52514ad675ae63f7", + "sha256:bcac356d62edd330080aed082e78d4b580ff260a677508718f88016333e2c9c5", + "sha256:e7514d7a48c063226b7d06617cbb12a14278d4323a065a8d46a7962686ce2e95", + "sha256:f07909cd9fc08c52d294b1570bba92186181ca01fe3dc9ffba68955273dd7362" + ], + "index": "pypi", + "version": "==0.14.0" + }, + "wcwidth": { + "hashes": [ + "sha256:8fd29383f539be45b20bd4df0dc29c20ba48654a41e661925e612311e9f3c603", + "sha256:f28b3e8a6483e5d49e7f8949ac1a78314e740333ae305b4ba5defd3e74fb37a8" + ], + "index": "pypi", + "version": "==0.1.8" + }, + "websockets": { + "hashes": [ + "sha256:0e4fb4de42701340bd2353bb2eee45314651caa6ccee80dbd5f5d5978888fed5", + "sha256:1d3f1bf059d04a4e0eb4985a887d49195e15ebabc42364f4eb564b1d065793f5", + "sha256:20891f0dddade307ffddf593c733a3fdb6b83e6f9eef85908113e628fa5a8308", + "sha256:295359a2cc78736737dd88c343cd0747546b2174b5e1adc223824bcaf3e164cb", + "sha256:2db62a9142e88535038a6bcfea70ef9447696ea77891aebb730a333a51ed559a", + "sha256:3762791ab8b38948f0c4d281c8b2ddfa99b7e510e46bd8dfa942a5fff621068c", + "sha256:3db87421956f1b0779a7564915875ba774295cc86e81bc671631379371af1170", + "sha256:3ef56fcc7b1ff90de46ccd5a687bbd13a3180132268c4254fc0fa44ecf4fc422", + "sha256:4f9f7d28ce1d8f1295717c2c25b732c2bc0645db3215cf757551c392177d7cb8", + "sha256:5c01fd846263a75bc8a2b9542606927cfad57e7282965d96b93c387622487485", + "sha256:5c65d2da8c6bce0fca2528f69f44b2f977e06954c8512a952222cea50dad430f", + "sha256:751a556205d8245ff94aeef23546a1113b1dd4f6e4d102ded66c39b99c2ce6c8", + "sha256:7ff46d441db78241f4c6c27b3868c9ae71473fe03341340d2dfdbe8d79310acc", + "sha256:965889d9f0e2a75edd81a07592d0ced54daa5b0785f57dc429c378edbcffe779", + "sha256:9b248ba3dd8a03b1a10b19efe7d4f7fa41d158fdaa95e2cf65af5a7b95a4f989", + "sha256:9bef37ee224e104a413f0780e29adb3e514a5b698aabe0d969a6ba426b8435d1", + "sha256:c1ec8db4fac31850286b7cd3b9c0e1b944204668b8eb721674916d4e28744092", + "sha256:c8a116feafdb1f84607cb3b14aa1418424ae71fee131642fc568d21423b51824", + "sha256:ce85b06a10fc65e6143518b96d3dca27b081a740bae261c2fb20375801a9d56d", + "sha256:d705f8aeecdf3262379644e4b55107a3b55860eb812b673b28d0fbc347a60c55", + "sha256:e898a0863421650f0bebac8ba40840fc02258ef4714cb7e1fd76b6a6354bda36", + "sha256:f8a7bff6e8664afc4e6c28b983845c5bc14965030e3fb98789734d416af77c4b" + ], + "index": "pypi", + "version": "==8.1" + }, + "zipp": { + "hashes": [ + "sha256:8dda78f06bd1674bd8720df8a50bb47b6e1233c503a4eed8e7810686bde37656", + "sha256:d38fbe01bbf7a3593a32bc35a9c4453c32bc42b98c377f9bff7e9f8da157786c" + ], + "index": "pypi", + "version": "==1.0.0" + } + }, + "develop": {} +} diff --git a/server/api/src/__init__.py b/server/api/src/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/server/api/src/__main__.py b/server/api/src/__main__.py new file mode 100644 index 000000000..bfa303311 --- /dev/null +++ b/server/api/src/__main__.py @@ -0,0 +1,32 @@ +import os +import time +from datetime import datetime +from multiprocessing import Process + +import db +import pb +import app +from settings import Server + + +def update(): + time.sleep(5) + + last_updated = db.info.last_updated() + time_since_update = datetime.utcnow() - last_updated + if time_since_update.days >= 1: + db.requests.update() + + if pb.enabled: + pb.populate() + + +if __name__ == '__main__': + + if Server.UPDATE_ON_START: + Process(target=update).start() + + if Server.DEBUG: + print(os.environ) + + app.start() diff --git a/server/api/src/settings.py b/server/api/src/settings.py index b0e763bf5..6dd328b9d 100644 --- a/server/api/src/settings.py +++ b/server/api/src/settings.py @@ -10,7 +10,7 @@ class Version: class Server: - HOST = '0.0.0.0' + HOST = env('HOST') PORT = env('PORT', to.INT) DEBUG = env('DEBUG', to.BOOL) ACCESS_LOG = env('ACCESS_LOG', to.BOOL)