Skip to content
This repository was archived by the owner on Sep 2, 2022. It is now read-only.

Commit 94d0834

Browse files
authored
Merge pull request #1 from apilytics/initial-version
Initial version
2 parents 689dd41 + 4f5c414 commit 94d0834

27 files changed

Lines changed: 1858 additions & 0 deletions

.flake8

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[flake8]
2+
exclude =
3+
.venv
4+
ignore =
5+
# Whitespace before ':': Not PEP 8 compliant and clashes with Black.
6+
E203,
7+
# Line length: Black handles them so Flake doesn't have to.
8+
E501,
9+
# Line break before binary operator: Not PEP 8 compliant and clashes with Black.
10+
W503,
11+
per_file_ignores =
12+
# Allow unused imports in __init__ files.
13+
__init__.py:F401,

.github/check_commits.sh

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#!/bin/sh
2+
3+
head="$(git remote show origin | awk '/HEAD branch/ {print $NF}')"
4+
current="$(git rev-parse HEAD)"
5+
6+
if ! git merge-base --is-ancestor "origin/${head}" "$current"; then
7+
printf "Forgotten to rebase on top of %s.\nExiting with error!\n" "$head"
8+
exit 1
9+
fi
10+
11+
if [ "$(git rev-list --count --merges "origin/${head}..${current}")" -ne 0 ]; then
12+
printf "There are merge commits on the branch.\nExiting with error!\n"
13+
exit 1
14+
fi
15+
16+
echo Branch up-to-date and commits ok.

.github/workflows/cd.yml

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
name: "CD"
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
version:
7+
description: "Version of the release, e.g. 1.0.0"
8+
required: true
9+
10+
jobs:
11+
release:
12+
name: "Release"
13+
runs-on: ubuntu-latest
14+
steps:
15+
- name: "Checkout code"
16+
uses: actions/checkout@v2
17+
with:
18+
token: ${{ secrets.GH_PAT }}
19+
20+
- name: "Update the changelog"
21+
# Find the first line that starts with `###` or `## [<number>` from the CHANGELOG and insert the new version header before it.
22+
run: >
23+
current_date="$(date '+%Y-%m-%d')"
24+
&& sed -i "0,/^\(###\|## *\[[0-9]\).*/{s//## [${{ github.event.inputs.version }}] - ${current_date}\n\n&/}" CHANGELOG.md
25+
26+
- name: "Bump pyproject.toml to new version"
27+
run: sed -i 's/^version *=.*/version = "${{ github.event.inputs.version }}"/' pyproject.toml
28+
29+
- name: "Extract version's changelog for release notes and tag message"
30+
# Find the lines between the first `## [<number>` and the second `## [<number>`.
31+
run: sed '1,/^## *\[[0-9]/d;/^## *\[[0-9]/Q' CHANGELOG.md > release_notes.txt
32+
33+
- name: "Set up Python"
34+
id: setup-python
35+
uses: actions/setup-python@v2
36+
with:
37+
python-version: '3.7'
38+
39+
- name: "Install Poetry"
40+
uses: snok/install-poetry@5e4414407e59f94f2148bcb253917dfc22dee7d9 # v1.3.0
41+
with:
42+
virtualenvs-create: true
43+
virtualenvs-in-project: true
44+
45+
- name: "Build the wheel"
46+
run: poetry build
47+
48+
- name: "Publish to PyPI"
49+
run: poetry publish
50+
env:
51+
POETRY_PYPI_TOKEN_PYPI: ${{ secrets.PYPI_TOKEN }}
52+
53+
- name: "Commit and tag the changes"
54+
uses: EndBug/add-and-commit@8c12ff729a98cfbcd3fe38b49f55eceb98a5ec02 # v7.5.0
55+
with:
56+
add: '["pyproject.toml", "CHANGELOG.md"]'
57+
message: 'Release ${{ github.event.inputs.version }}'
58+
tag: 'v${{ github.event.inputs.version }} --annotate'
59+
default_author: github_actions
60+
61+
- name: "Create a GitHub release"
62+
uses: softprops/action-gh-release@1e07f4398721186383de40550babbdf2b84acfc5 # v1
63+
with:
64+
tag_name: v${{ github.event.inputs.version }}
65+
name: v${{ github.event.inputs.version }}
66+
body_path: release_notes.txt

.github/workflows/ci.yml

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
name: "CI"
2+
3+
on:
4+
push:
5+
branches: [master]
6+
pull_request:
7+
8+
concurrency:
9+
group: ci-${{ github.head_ref }}
10+
cancel-in-progress: true
11+
12+
jobs:
13+
commits:
14+
name: "Commits"
15+
if: ${{ github.event_name == 'pull_request' }}
16+
runs-on: ubuntu-latest
17+
steps:
18+
- name: "Checkout code"
19+
uses: actions/checkout@v2
20+
with:
21+
ref: ${{ github.event.pull_request.head.sha }}
22+
fetch-depth: 0
23+
24+
- name: "Check commits of the PR branch"
25+
run: ./.github/check_commits.sh
26+
27+
linters:
28+
name: "Linters"
29+
needs: commits
30+
if: ${{ !failure() }}
31+
runs-on: ubuntu-latest
32+
steps:
33+
- name: "Checkout code"
34+
uses: actions/checkout@v2
35+
36+
- name: "Set up Python"
37+
id: setup-python
38+
uses: actions/setup-python@v2
39+
with:
40+
python-version: '3.7'
41+
42+
- name: "Install Poetry"
43+
uses: snok/install-poetry@5e4414407e59f94f2148bcb253917dfc22dee7d9 # v1.3.0
44+
with:
45+
virtualenvs-create: true
46+
virtualenvs-in-project: true
47+
48+
- name: "Load cached venv"
49+
id: cached-poetry-dependencies
50+
uses: actions/cache@v2
51+
with:
52+
path: .venv
53+
key: venv-${{ runner.os }}-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('**/poetry.lock') }}
54+
55+
- name: "Install dependencies"
56+
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
57+
run: poetry install --no-root
58+
59+
- name: "Run linters"
60+
run: |
61+
source "$VENV"
62+
isort --check-only --diff .
63+
flake8 .
64+
black --check --diff .
65+
66+
build:
67+
name: "Build"
68+
needs: commits
69+
if: ${{ !failure() }}
70+
runs-on: ubuntu-latest
71+
steps:
72+
- name: "Checkout code"
73+
uses: actions/checkout@v2
74+
75+
- name: "Set up Python"
76+
id: setup-python
77+
uses: actions/setup-python@v2
78+
with:
79+
python-version: '3.7'
80+
81+
- name: "Install Poetry"
82+
uses: snok/install-poetry@5e4414407e59f94f2148bcb253917dfc22dee7d9 # v1.3.0
83+
with:
84+
virtualenvs-create: true
85+
virtualenvs-in-project: true
86+
87+
- name: "Build the wheel"
88+
run: poetry build
89+
90+
- name: "Install from the wheel"
91+
run: pip install dist/*.whl
92+
93+
tests:
94+
name: "Tests"
95+
needs: [linters, build]
96+
strategy:
97+
fail-fast: true
98+
matrix:
99+
python-version: ['3.7', '3.8', '3.9', '3.10']
100+
101+
runs-on: ubuntu-latest
102+
steps:
103+
- name: "Checkout code"
104+
uses: actions/checkout@v2
105+
106+
- name: "Set up Python ${{ matrix.python-version }}"
107+
id: setup-python
108+
uses: actions/setup-python@v2
109+
with:
110+
python-version: ${{ matrix.python-version }}
111+
112+
- name: "Install Poetry"
113+
uses: snok/install-poetry@5e4414407e59f94f2148bcb253917dfc22dee7d9 # v1.3.0
114+
with:
115+
virtualenvs-create: true
116+
virtualenvs-in-project: true
117+
118+
- name: "Load cached venv"
119+
id: cached-poetry-dependencies
120+
uses: actions/cache@v2
121+
with:
122+
path: .venv
123+
key: venv-${{ runner.os }}-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('**/poetry.lock') }}
124+
125+
- name: "Install dependencies"
126+
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
127+
run: poetry install --no-root
128+
129+
- name: "Install the package"
130+
run: poetry install
131+
132+
- name: "Run type-checking"
133+
run: |
134+
source "$VENV"
135+
mypy .
136+
137+
- name: "Run tests"
138+
run: |
139+
source "$VENV"
140+
pytest --verbose --cov=. --cov-report=xml .
141+
142+
- name: "Upload coverage"
143+
if: matrix.python-version == '3.7'
144+
uses: codecov/codecov-action@f32b3a3741e1053eb607407145bc9619351dc93b # v2.1.0
145+
with:
146+
files: coverage.xml

.gitignore

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
.DS_Store
2+
3+
__pycache__/
4+
*.py[cod]
5+
6+
dist/
7+
8+
htmlcov/
9+
.coverage
10+
.pytest_cache/
11+
.mypy_cache/
12+
13+
.python-version
14+
15+
.idea/
16+
.vscode/

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Changelog
2+
3+
All notable changes to this project will be documented in this file.
4+
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7+
8+
## [Unreleased]
9+
10+
### Added
11+
12+
- Initial version with Django and FastAPI support.

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2022 Apilytics
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# apilytics-python
2+
3+
[![pypi](https://img.shields.io/pypi/v/apilytics)](https://pypi.org/project/apilytics/)
4+
[![ci](https://github.com/apilytics/apilytics-python/actions/workflows/ci.yml/badge.svg)](https://github.com/apilytics/apilytics-python/actions/workflows/ci.yml)
5+
[![codecov](https://codecov.io/gh/apilytics/apilytics-python/branch/master/graph/badge.svg?token=GIW1NZ7UAJ)](https://codecov.io/gh/apilytics/apilytics-python)
6+
[![mypy checked](http://www.mypy-lang.org/static/mypy_badge.svg)](http://mypy-lang.org)
7+
[![code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
8+
[![python versions](https://img.shields.io/pypi/pyversions/apilytics)](#what-python-versions-does-the-package-work-with)
9+
[![license](https://img.shields.io/pypi/l/apilytics.svg)](https://github.com/apilytics/apilytics-python/blob/master/LICENSE)
10+
11+
## Installation
12+
13+
1. Sign up and get your API key from https://apilytics.io - we offer a completely free trial with no credit card required!
14+
15+
2. Install this package:
16+
```sh
17+
pip install apilytics
18+
```
19+
20+
3. Enable the middleware and set your API key:
21+
*A good practice is to securely store the API key as an environment variable.
22+
You can leave the env variable unset in e.g. development and test environments,
23+
the middleware will be automatically disabled if the key is `None`.*
24+
25+
### Django:
26+
27+
`settings.py`:
28+
```python
29+
import os
30+
31+
APILYTICS_API_KEY = os.getenv("APILYTICS_API_KEY")
32+
33+
MIDDLEWARE = [
34+
"apilytics.django.ApilyticsMiddleware",
35+
]
36+
```
37+
38+
### FastAPI:
39+
40+
`main.py`:
41+
42+
```python
43+
import os
44+
45+
from apilytics.fastapi import ApilyticsMiddleware
46+
from fastapi import FastAPI
47+
48+
app = FastAPI()
49+
50+
app.add_middleware(ApilyticsMiddleware, api_key=os.getenv("APILYTICS_API_KEY"))
51+
```
52+
53+
### Other Python Frameworks:
54+
55+
You can easily build your own middleware which measures the execution time and sends the metrics:
56+
57+
`my_apilytics_middleware.py`:
58+
```python
59+
import os
60+
61+
from apilytics.core import ApilyticsSender
62+
63+
64+
def my_apilytics_middleware(request, get_response):
65+
with ApilyticsSender(
66+
api_key=os.getenv("APILYTICS_API_KEY"),
67+
path=request.path,
68+
method=request.method,
69+
) as sender:
70+
response = get_response(request)
71+
sender.set_response_info(status_code=response.status_code)
72+
return response
73+
```
74+
75+
## Frequently Asked Questions
76+
77+
### Does the middleware slow down my backend?
78+
79+
- No. The middleware does all of its requests to the Apilytics API in a background thread pool,
80+
so it will not slow down your normal request handling.
81+
82+
### What 3rd party dependencies does `apilytics` have?
83+
84+
- None besides the frameworks that you use it in.
85+
86+
### What Python versions does the package work with?
87+
88+
- `apilytics` is tested to work on all the currently [supported versions of Python](https://devguide.python.org/#status-of-python-branches): 3.7, 3.8, 3.9, and 3.10.

apilytics/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)