Metadata-Version: 2.4
Name: codeforlife
Version: 0.29.3
Summary: Code for Life's common code.
Home-page: https://github.com/ocadotechnology/codeforlife-package-python
Author: Ocado
Author-email: code-for-life-full-time-xd@ocado.com
Requires-Python: ==3.12.*
Description-Content-Type: text/markdown
License-File: LICENSE.md
Requires-Dist: amqp==5.3.1; python_version >= "3.6"
Requires-Dist: asgiref==3.9.2; python_version >= "3.9"
Requires-Dist: asttokens==3.0.0; python_version >= "3.8"
Requires-Dist: billiard==4.2.2; python_version >= "3.7"
Requires-Dist: boto3==1.36.14; python_version >= "3.8"
Requires-Dist: botocore==1.36.26; python_version >= "3.8"
Requires-Dist: celery[sqs]==5.4.0; python_version >= "3.8"
Requires-Dist: certifi==2025.8.3; python_version >= "3.7"
Requires-Dist: cffi==1.17.1; platform_python_implementation != "PyPy"
Requires-Dist: cfl-common==8.9.6
Requires-Dist: charset-normalizer==3.4.3; python_version >= "3.7"
Requires-Dist: click==8.3.0; python_version >= "3.10"
Requires-Dist: click-didyoumean==0.3.1; python_full_version >= "3.6.2"
Requires-Dist: click-plugins==1.1.1.2
Requires-Dist: click-repl==0.3.0; python_version >= "3.6"
Requires-Dist: codeforlife-portal==8.9.6
Requires-Dist: cryptography==44.0.1; python_version >= "3.7" and python_full_version not in "3.9.0, 3.9.1"
Requires-Dist: decorator==5.2.1; python_version >= "3.8"
Requires-Dist: diff-match-patch==20241021; python_version >= "3.7"
Requires-Dist: django==5.1.13; python_version >= "3.10"
Requires-Dist: django-classy-tags==4.1.0; python_version >= "3.8"
Requires-Dist: django-cors-headers==4.7.0; python_version >= "3.9"
Requires-Dist: django-countries==7.6.1
Requires-Dist: django-csp==3.8
Requires-Dist: django-filter==25.1; python_version >= "3.9"
Requires-Dist: django-formtools==2.5.1; python_version >= "3.8"
Requires-Dist: django-import-export==4.2.0; python_version >= "3.9"
Requires-Dist: django-otp==1.6.1; python_version >= "3.7"
Requires-Dist: django-phonenumber-field==8.1.0; python_version >= "3.9"
Requires-Dist: django-pipeline==4.0.0; python_version >= "3.9"
Requires-Dist: django-preventconcurrentlogins==0.8.2
Requires-Dist: django-ratelimit==3.0.1; python_version >= "3.4"
Requires-Dist: django-recaptcha==4.0.0
Requires-Dist: django-reverse-js==0.1.8; python_version >= "3.10"
Requires-Dist: django-sekizai==4.1.0; python_version >= "3.8"
Requires-Dist: django-storages[s3]==1.14.6; python_version >= "3.7"
Requires-Dist: django-treebeard==4.7.1; python_version >= "3.8"
Requires-Dist: django-two-factor-auth==1.17.0; python_version >= "3.8"
Requires-Dist: djangorestframework==3.16.0; python_version >= "3.9"
Requires-Dist: executing==2.2.1; python_version >= "3.8"
Requires-Dist: gunicorn==23.0.0; python_version >= "3.7"
Requires-Dist: h11==0.16.0; python_version >= "3.8"
Requires-Dist: hiredis==3.2.1
Requires-Dist: idna==3.10; python_version >= "3.6"
Requires-Dist: importlib-metadata==4.13.0; python_version >= "3.7"
Requires-Dist: ipython==9.6.0; python_version >= "3.11"
Requires-Dist: ipython-pygments-lexers==1.1.1; python_version >= "3.8"
Requires-Dist: jedi==0.19.2; python_version >= "3.6"
Requires-Dist: jmespath==1.0.1; python_version >= "3.7"
Requires-Dist: kombu[sqs]==5.5.4; python_version >= "3.8"
Requires-Dist: libsass==0.23.0; python_version >= "3.8"
Requires-Dist: matplotlib-inline==0.1.7; python_version >= "3.8"
Requires-Dist: more-itertools==8.7.0; python_version >= "3.5"
Requires-Dist: numpy==2.3.2; python_version >= "3.11"
Requires-Dist: packaging==25.0; python_version >= "3.8"
Requires-Dist: pandas==2.3.2; python_version >= "3.9"
Requires-Dist: parso==0.8.5; python_version >= "3.6"
Requires-Dist: pexpect==4.9.0; sys_platform != "win32" and sys_platform != "emscripten"
Requires-Dist: pgeocode==0.4.0; python_version >= "3.8"
Requires-Dist: phonenumbers==8.12.12
Requires-Dist: pillow==11.3.0; python_version >= "3.9"
Requires-Dist: prompt-toolkit==3.0.52; python_version >= "3.8"
Requires-Dist: psutil==7.0.0; python_version >= "3.6"
Requires-Dist: psycopg2-binary==2.9.9; python_version >= "3.7"
Requires-Dist: ptyprocess==0.7.0
Requires-Dist: pure-eval==0.2.3
Requires-Dist: pycparser==2.22; python_version >= "3.8"
Requires-Dist: pycurl==7.45.7; python_version >= "3.5"
Requires-Dist: pygments==2.19.2; python_version >= "3.8"
Requires-Dist: pyhamcrest==2.0.2; python_version >= "3.5"
Requires-Dist: pyjwt==2.6.0; python_version >= "3.7"
Requires-Dist: pyotp==2.9.0; python_version >= "3.7"
Requires-Dist: pypng==0.20220715.0
Requires-Dist: python-dateutil==2.9.0.post0; python_version >= "2.7" and python_version not in "3.0, 3.1, 3.2, 3.3"
Requires-Dist: python-dotenv==1.0.1; python_version >= "3.8"
Requires-Dist: pytz==2025.2
Requires-Dist: pyyaml==6.0.2; python_version >= "3.8"
Requires-Dist: qrcode==7.4.2; python_version >= "3.7"
Requires-Dist: rapid-router==7.6.5
Requires-Dist: redis[hiredis]==5.2.1; python_version >= "3.8"
Requires-Dist: regex==2024.11.6; python_version >= "3.8"
Requires-Dist: reportlab==4.4.2; python_version >= "3.7" and python_version < "4"
Requires-Dist: requests==2.32.5; python_version >= "3.9"
Requires-Dist: requests-toolbelt==1.0.0; python_version >= "2.7" and python_version not in "3.0, 3.1, 3.2, 3.3"
Requires-Dist: s3transfer==0.11.3; python_version >= "3.8"
Requires-Dist: setuptools==80.9.0; python_version >= "3.9"
Requires-Dist: six==1.17.0; python_version >= "2.7" and python_version not in "3.0, 3.1, 3.2, 3.3"
Requires-Dist: sqlparse==0.5.3; python_version >= "3.8"
Requires-Dist: stack-data==0.6.3
Requires-Dist: tablib==3.7.0; python_version >= "3.9"
Requires-Dist: traitlets==5.14.3; python_version >= "3.8"
Requires-Dist: typing-extensions==4.15.0; python_version >= "3.9"
Requires-Dist: tzdata==2025.2; python_version >= "2"
Requires-Dist: urllib3==2.5.0; python_version >= "3.9"
Requires-Dist: uvicorn==0.37.0; python_version >= "3.9"
Requires-Dist: uvicorn-worker==0.2.0; python_version >= "3.8"
Requires-Dist: vine==5.1.0; python_version >= "3.6"
Requires-Dist: wcwidth==0.2.14; python_version >= "3.6"
Requires-Dist: wheel==0.45.1; python_version >= "3.8"
Requires-Dist: whitenoise==6.9.0; python_version >= "3.9"
Requires-Dist: zipp==3.23.0; python_version >= "3.9"
Provides-Extra: dev
Requires-Dist: asgiref==3.9.2; python_version >= "3.9" and extra == "dev"
Requires-Dist: astroid==3.2.4; python_full_version >= "3.8.0" and extra == "dev"
Requires-Dist: black==24.8.0; python_version >= "3.8" and extra == "dev"
Requires-Dist: boto3-stubs[essential]==1.38.39; python_version >= "3.8" and extra == "dev"
Requires-Dist: botocore-stubs==1.40.33; python_version >= "3.9" and extra == "dev"
Requires-Dist: celery-types==0.23.0; (python_version >= "3.9" and python_version < "4.0") and extra == "dev"
Requires-Dist: certifi==2025.8.3; python_version >= "3.7" and extra == "dev"
Requires-Dist: charset-normalizer==3.4.3; python_version >= "3.7" and extra == "dev"
Requires-Dist: click==8.3.0; python_version >= "3.10" and extra == "dev"
Requires-Dist: coverage[toml]==7.10.7; python_version >= "3.9" and extra == "dev"
Requires-Dist: dill==0.4.0; python_version >= "3.11" and extra == "dev"
Requires-Dist: django==5.1.13; python_version >= "3.10" and extra == "dev"
Requires-Dist: django-extensions==3.2.1; python_version >= "3.6" and extra == "dev"
Requires-Dist: django-stubs[compatible-mypy]==4.2.6; python_version >= "3.8" and extra == "dev"
Requires-Dist: django-stubs-ext==5.2.7; python_version >= "3.10" and extra == "dev"
Requires-Dist: django-test-migrations==1.2.0; (python_version >= "3.6" and python_version < "4.0") and extra == "dev"
Requires-Dist: djangorestframework-stubs[compatible-mypy]==3.14.4; python_version >= "3.8" and extra == "dev"
Requires-Dist: execnet==2.1.1; python_version >= "3.8" and extra == "dev"
Requires-Dist: idna==3.10; python_version >= "3.6" and extra == "dev"
Requires-Dist: iniconfig==2.1.0; python_version >= "3.8" and extra == "dev"
Requires-Dist: isort==5.13.2; python_full_version >= "3.8.0" and extra == "dev"
Requires-Dist: mccabe==0.7.0; python_version >= "3.6" and extra == "dev"
Requires-Dist: mypy==1.6.1; python_version >= "3.8" and extra == "dev"
Requires-Dist: mypy-boto3-cloudformation==1.38.31; extra == "dev"
Requires-Dist: mypy-boto3-dynamodb==1.38.4; extra == "dev"
Requires-Dist: mypy-boto3-ec2==1.38.45; extra == "dev"
Requires-Dist: mypy-boto3-lambda==1.38.40; extra == "dev"
Requires-Dist: mypy-boto3-rds==1.38.46; extra == "dev"
Requires-Dist: mypy-boto3-s3==1.38.44; python_version >= "3.8" and extra == "dev"
Requires-Dist: mypy-boto3-sqs==1.38.0; extra == "dev"
Requires-Dist: mypy-extensions==1.1.0; python_version >= "3.8" and extra == "dev"
Requires-Dist: packaging==25.0; python_version >= "3.8" and extra == "dev"
Requires-Dist: pathspec==0.12.1; python_version >= "3.8" and extra == "dev"
Requires-Dist: platformdirs==4.5.0; python_version >= "3.10" and extra == "dev"
Requires-Dist: pluggy==1.6.0; python_version >= "3.9" and extra == "dev"
Requires-Dist: psutil==7.0.0; python_version >= "3.6" and extra == "dev"
Requires-Dist: pydot==1.4.2; (python_version >= "2.7" and python_version not in "3.0, 3.1, 3.2, 3.3") and extra == "dev"
Requires-Dist: pylint==3.2.7; python_full_version >= "3.8.0" and extra == "dev"
Requires-Dist: pylint-django==2.5.5; (python_version >= "3.7" and python_version < "4.0") and extra == "dev"
Requires-Dist: pylint-plugin-utils==0.9.0; (python_version >= "3.9" and python_version < "4.0") and extra == "dev"
Requires-Dist: pyparsing==3.0.9; python_full_version >= "3.6.8" and extra == "dev"
Requires-Dist: pytest==8.3.3; python_version >= "3.8" and extra == "dev"
Requires-Dist: pytest-cov==5.0.0; python_version >= "3.8" and extra == "dev"
Requires-Dist: pytest-django==4.5.2; python_version >= "3.5" and extra == "dev"
Requires-Dist: pytest-env==0.8.1; python_version >= "3.7" and extra == "dev"
Requires-Dist: pytest-xdist[psutil]==3.5.0; python_version >= "3.7" and extra == "dev"
Requires-Dist: requests==2.32.5; python_version >= "3.9" and extra == "dev"
Requires-Dist: sqlparse==0.5.3; python_version >= "3.8" and extra == "dev"
Requires-Dist: tomlkit==0.13.3; python_version >= "3.8" and extra == "dev"
Requires-Dist: types-awscrt==0.27.6; python_version >= "3.8" and extra == "dev"
Requires-Dist: types-psutil==7.0.0.20250601; python_version >= "3.9" and extra == "dev"
Requires-Dist: types-pytz==2025.2.0.20250809; python_version >= "3.9" and extra == "dev"
Requires-Dist: types-pyyaml==6.0.12.20250915; python_version >= "3.9" and extra == "dev"
Requires-Dist: types-regex==2024.11.6.20250403; python_version >= "3.9" and extra == "dev"
Requires-Dist: types-requests==2.32.4.20250913; python_version >= "3.9" and extra == "dev"
Requires-Dist: types-s3transfer==0.13.1; python_version >= "3.8" and extra == "dev"
Requires-Dist: typing-extensions==4.15.0; python_version >= "3.9" and extra == "dev"
Requires-Dist: urllib3==2.5.0; python_version >= "3.9" and extra == "dev"
Dynamic: author
Dynamic: author-email
Dynamic: description
Dynamic: description-content-type
Dynamic: home-page
Dynamic: license-file
Dynamic: provides-extra
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary

# codeforlife-package-python

This repo contains CFL's python package. This will be installed into all backend services.

## LICENCE

In accordance with the [Terms of Use](https://www.codeforlife.education/terms#terms)
of the Code for Life website, all copyright, trademarks, and other
intellectual property rights in and relating to Code for Life (including all
content of the Code for Life website, the Rapid Router application, the
Kurono application, related software (including any drawn and/or animated
avatars, whether such avatars have any modifications) and any other games,
applications or any other content that we make available from time to time) are
owned by Ocado Innovation Limited.

The source code of the Code for Life portal, the Rapid Router application
and the Kurono/aimmo application are [licensed under the GNU Affero General
Public License](https://github.com/ocadotechnology/codeforlife-workspace/blob/main/LICENSE.md).
All other assets including images, logos, sounds etc., are not covered by
this licence and no-one may copy, modify, distribute, show in public or
create any derivative work from these assets.

## Installation

To install this package, do one of the following options.

Make sure to:

1. install the package with the required python version.
1. replace the [package version number](https://pypi.org/project/codeforlife/#history) ("0.0.0") with the same value for both the production and development dependencies or you'll get conflict errors.

**Option 1:** Run both `pipenv install` commands:

```bash
# Install as a production dependency.
pipenv install codeforlife==0.0.0

# Install as a development dependency.
pipenv install --dev codeforlife[dev]==0.0.0
```

**Option 2:** Add a row to `[packages]` and `[dev-packages]` in `Pipfile`:

```toml
[packages]
codeforlife = "==0.0.0"

[dev-packages]
codeforlife = {version = "==0.0.0", extras = ["dev"]}
```

### Installing a GitHub Branch

You may wish to install and integrate your changes into a CFL backend before it's been peer-reviewed.

Make sure to:

1. replace the branch name ("BRANCH_HERE") with the same value for both the production and development dependencies or you'll get conflict errors.
1. replace the organization name ("ORG_HERE") with the same value for both the production and development dependencies or you'll get conflict errors.

```toml
[packages]
codeforlife = {ref = "BRANCH_HERE", git = "https://github.com/ORG_HERE/codeforlife-package-python.git"}

[dev-packages]
codeforlife = {ref = "BRANCH_HERE", git = "https://github.com/ORG_HERE/codeforlife-package-python.git", extras = ["dev"]}
```

## Version Release

New versions of this package are automatically created by [this](.github/workflows/main.yml) GitHub Actions workflow.

Versions are determined using the [semantic-release commit message format](https://semantic-release.gitbook.io/semantic-release/#commit-message-format).

If a new version is successfully released, it will create:

1. A new tag [on GitHub](https://github.com/ocadotechnology/codeforlife-package-python/tags).
1. A new release [on GitHub](https://github.com/ocadotechnology/codeforlife-package-python/releases).
1. A new release [on PyPI](https://pypi.org/project/codeforlife/#history).
