Skip to content

Commit e247d87

Browse files
committed
Break the SDK out into its own repo
I prototyped this in https://github.com/negz/function-auto-python. Signed-off-by: Nic Cope <[email protected]>
1 parent e930e1d commit e247d87

File tree

16 files changed

+1231
-1
lines changed

16 files changed

+1231
-1
lines changed

.github/ISSUE_TEMPLATE/bug_report.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
---
2+
name: Bug Report
3+
about: Help us diagnose and fix bugs in this Function
4+
labels: bug
5+
---
6+
<!--
7+
Thank you for helping to improve Crossplane!
8+
9+
Please be sure to search for open issues before raising a new one. We use issues
10+
for bug reports and feature requests. Please find us at https://slack.crossplane.io
11+
for questions, support, and discussion.
12+
-->
13+
14+
### What happened?
15+
<!--
16+
Please let us know what behaviour you expected and how this Function diverged
17+
from that behaviour.
18+
-->
19+
20+
21+
### How can we reproduce it?
22+
<!--
23+
Help us to reproduce your bug as succinctly and precisely as possible. Artifacts
24+
such as example manifests or a script that triggers the issue are highly
25+
appreciated!
26+
-->
27+
28+
### What environment did it happen in?
29+
Function version:
30+
31+
<!--
32+
Include at least the version or commit of Crossplane you were running. Consider
33+
also including your:
34+
35+
* Cloud provider or hardware configuration
36+
* Kubernetes version (use `kubectl version`)
37+
* Kubernetes distribution (e.g. Tectonic, GKE, OpenShift)
38+
* OS (e.g. from /etc/os-release)
39+
* Kernel (e.g. `uname -a`)
40+
-->
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
---
2+
name: Feature Request
3+
about: Help us make this Function more useful
4+
labels: enhancement
5+
---
6+
<!--
7+
Thank you for helping to improve Crossplane!
8+
9+
Please be sure to search for open issues before raising a new one. We use issues
10+
for bug reports and feature requests. Please find us at https://slack.crossplane.io
11+
for questions, support, and discussion.
12+
-->
13+
14+
### What problem are you facing?
15+
<!--
16+
Please tell us a little about your use case - it's okay if it's hypothetical!
17+
Leading with this context helps frame the feature request so we can ensure we
18+
implement it sensibly.
19+
--->
20+
21+
### How could this Function help solve your problem?
22+
<!--
23+
Let us know how you think this Function could help with your use case.
24+
-->

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<!--
2+
Thank you for helping to improve Crossplane!
3+
4+
Please read through https://git.io/fj2m9 if this is your first time opening a
5+
Crossplane pull request. Find us in https://slack.crossplane.io/messages/dev if
6+
you need any help contributing.
7+
-->
8+
9+
### Description of your changes
10+
11+
<!--
12+
Briefly describe what this pull request does, and how it is covered by tests.
13+
Be proactive - direct your reviewers' attention to anything that needs special
14+
consideration.
15+
16+
You MUST either [x] check or ~strikethrough~ every item in the checklist below.
17+
18+
We love pull requests that fix an open issue. If yours does, use the below line
19+
to indicate which issue it fixes, for example "Fixes #500".
20+
-->
21+
22+
Fixes #
23+
24+
I have:
25+
26+
- [ ] Read and followed Crossplane's [contribution process].
27+
- [ ] Added or updated unit tests for my change.
28+
29+
[contribution process]: https://git.io/fj2m9
30+
[docs]: https://docs.crossplane.io/contribute/contribute

.github/workflows/ci.yml

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
- release-*
8+
pull_request: {}
9+
workflow_dispatch:
10+
inputs:
11+
version:
12+
description: PyPI module version (e.g. v0.1.0)
13+
required: false
14+
15+
env:
16+
# Common versions
17+
PYTHON_VERSION: '3.11.5'
18+
19+
jobs:
20+
lint:
21+
runs-on: ubuntu-22.04
22+
steps:
23+
- name: Checkout
24+
uses: actions/checkout@v4
25+
26+
- name: Setup Python
27+
uses: actions/setup-python@v4
28+
with:
29+
python-version: ${{ env.PYTHON_VERSION }}
30+
31+
- name: Setup Hatch
32+
run: pipx install hatch==1.7.0
33+
34+
- name: Lint
35+
run: |
36+
hatch run lint:check-format
37+
hatch run lint:check
38+
39+
unit-test:
40+
runs-on: ubuntu-22.04
41+
steps:
42+
- name: Checkout
43+
uses: actions/checkout@v4
44+
45+
- name: Setup Python
46+
uses: actions/setup-python@v4
47+
with:
48+
python-version: ${{ env.PYTHON_VERSION }}
49+
50+
- name: Setup Hatch
51+
run: pipx install hatch==1.7.0
52+
53+
- name: Run Unit Tests
54+
run: hatch run test:unit
55+
56+
57+
build:
58+
runs-on: ubuntu-22.04
59+
steps:
60+
- name: Checkout
61+
uses: actions/checkout@v4
62+
63+
- name: Setup Python
64+
uses: actions/setup-python@v4
65+
with:
66+
python-version: ${{ env.PYTHON_VERSION }}
67+
68+
- name: Setup Hatch
69+
run: pipx install hatch==1.7.0
70+
71+
- name: Run Unit Tests
72+
run: hatch build
73+
74+
- name: Upload Sdist and Wheel to GitHub
75+
uses: actions/upload-artifact@v3
76+
with:
77+
name: module
78+
path: "dist/*"
79+
if-no-files-found: error
80+
retention-days: 1

README.md

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,39 @@
11
# function-sdk-python
2-
The Python SDK for composition functions
2+
[![CI](https://github.com/crossplane/function-sdk-python/actions/workflows/ci.yml/badge.svg)](https://github.com/crossplane/function-sdk-python/actions/workflows/ci.yml) ![GitHub release (latest SemVer)](https://img.shields.io/github/release/crossplane/function-sdk-python)
3+
4+
The [Python][python] SDK for writing [composition functions][functions].
5+
6+
This SDK is currently a beta. We try to avoid breaking changes, but it will not
7+
have a stable API until it reaches v1.0.0. It follows the same [contributing
8+
guidelines] as Crossplane.
9+
10+
To learn how to use this SDK:
11+
12+
* [Learn about how composition functions work][functions]
13+
14+
## Contributing
15+
16+
This project follows the Crossplane [contributing guidelines], where applicable
17+
to Python. It is linted, tested, and built using [Hatch][hatch].
18+
19+
Some useful commands:
20+
21+
```shell
22+
# Generate gRPC stubs.
23+
hatch run generate:protoc
24+
25+
# Lint the code, using ruff.
26+
hatch run lint:check
27+
hatch run lint:check-format
28+
29+
# Run unit tests.
30+
hatch run test:unit
31+
32+
# Build an sdist and wheel
33+
hatch build
34+
```
35+
36+
[python]: https://python.org
37+
[functions]: https://docs.crossplane.io/latest/concepts/composition-functions
38+
[contributing guidelines]: https://github.com/crossplane/crossplane/tree/master/contributing
39+
[hatch]: https://github.com/pypa/hatch

crossplane/function/logging.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
"""Logging utilities for composition functions."""
2+
3+
4+
import enum
5+
import logging
6+
7+
import structlog
8+
9+
10+
class Level(enum.Enum):
11+
"""Supported log levels."""
12+
13+
DISABLED = 0
14+
DEBUG = 1
15+
INFO = 2
16+
17+
18+
def configure(level: Level = Level.INFO) -> None:
19+
"""Configure logging.
20+
21+
Args:
22+
level: What log level to enable.
23+
24+
Must be called before calling get_logger. When debug logging is enabled logs
25+
will be printed in a human readable fashion. When not enabled, logs will be
26+
printed as JSON lines.
27+
"""
28+
29+
def dropper(logger, method_name, event_dict): # noqa: ARG001 # We need this signature.
30+
raise structlog.DropEvent
31+
32+
if level == Level.DISABLED:
33+
structlog.configure(processors=[dropper])
34+
return
35+
36+
processors = [
37+
structlog.stdlib.add_log_level,
38+
structlog.processors.CallsiteParameterAdder(
39+
{
40+
structlog.processors.CallsiteParameter.FILENAME,
41+
structlog.processors.CallsiteParameter.LINENO,
42+
}
43+
),
44+
]
45+
46+
if level == Level.DEBUG:
47+
structlog.configure(
48+
processors=[
49+
*processors,
50+
structlog.processors.TimeStamper(fmt="iso"),
51+
structlog.dev.ConsoleRenderer(),
52+
]
53+
)
54+
return
55+
56+
# Attempt to match function-sdk-go's production logger.
57+
structlog.configure(
58+
processors=[
59+
*processors,
60+
structlog.processors.dict_tracebacks,
61+
structlog.processors.TimeStamper(key="ts"),
62+
structlog.processors.EventRenamer(to="msg"),
63+
structlog.processors.JSONRenderer(),
64+
],
65+
wrapper_class=structlog.make_filtering_bound_logger(logging.INFO),
66+
)
67+
68+
69+
def get_logger() -> structlog.stdlib.BoundLogger:
70+
"""Get a logger.
71+
72+
You must call configure before calling get_logger.
73+
"""
74+
return structlog.stdlib.get_logger()

0 commit comments

Comments
 (0)