Skip to content
This repository was archived by the owner on Oct 4, 2024. It is now read-only.

Commit 2e2335f

Browse files
authored
Merge pull request #458 from gilesknap/skeleton-merge
Skeleton merge - update to python 3.12
2 parents 1516059 + 78cbee5 commit 2e2335f

28 files changed

+707
-529
lines changed

.devcontainer/devcontainer.json

+33-51
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,50 @@
1-
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
2-
// https://github.com/microsoft/vscode-dev-containers/tree/v0.231.6/containers/python-3
1+
// For format details, see https://containers.dev/implementors/json_reference/
32
{
4-
"name": "Python 3",
3+
"name": "Python 3 Developer Container",
54
"build": {
6-
"dockerfile": "Dockerfile",
7-
"target": "developer",
8-
"context": "..",
9-
"args": {}
5+
"dockerfile": "../Dockerfile",
6+
"target": "build",
7+
// Only upgrade pip, we will install the project below
8+
"args": {
9+
"PIP_OPTIONS": "--upgrade pip"
10+
}
1011
},
1112
"remoteEnv": {
1213
"DISPLAY": "${localEnv:DISPLAY}"
1314
},
14-
// Set *default* container specific settings.json values on container create.
15-
"settings": {
16-
"python.defaultInterpreterPath": "/usr/local/bin/python",
17-
"python.linting.enabled": true,
18-
"python.linting.pylintEnabled": true,
19-
"python.formatting.autopep8Path": "/usr/local/py-utils/bin/autopep8",
20-
"python.formatting.blackPath": "/usr/local/py-utils/bin/black",
21-
"python.formatting.yapfPath": "/usr/local/py-utils/bin/yapf",
22-
"python.linting.banditPath": "/usr/local/py-utils/bin/bandit",
23-
"python.linting.flake8Path": "/usr/local/py-utils/bin/flake8",
24-
"python.linting.mypyPath": "/usr/local/py-utils/bin/mypy",
25-
"python.linting.pycodestylePath": "/usr/local/py-utils/bin/pycodestyle",
26-
"python.linting.pydocstylePath": "/usr/local/py-utils/bin/pydocstyle",
27-
"python.linting.pylintPath": "/usr/local/py-utils/bin/pylint"
28-
},
29-
// Add the IDs of extensions you want installed when the container is created.
30-
"extensions": [
31-
"ms-python.python",
32-
"ms-python.vscode-pylance",
33-
"streetsidesoftware.code-spell-checker",
34-
"ryanluker.vscode-coverage-gutters",
35-
"mhutchie.git-graph",
36-
"eamodio.gitlens",
37-
"gruntfuggly.todo-tree",
38-
"redhat.vscode-yaml",
39-
"nsd.vscode-epics",
40-
"alefragnani.bookmarks"
41-
],
15+
// Add the URLs of features you want added when the container is built.
4216
"features": {
43-
//"docker-from-docker": "20.10",
44-
"git": "os-provided"
17+
"ghcr.io/devcontainers/features/common-utils:1": {
18+
"username": "none",
19+
"upgradePackages": false
20+
}
21+
},
22+
"customizations": {
23+
"vscode": {
24+
// Add the IDs of extensions you want installed when the container is created.
25+
"extensions": [
26+
"ms-python.python",
27+
"tamasfe.even-better-toml",
28+
"redhat.vscode-yaml",
29+
"ryanluker.vscode-coverage-gutters"
30+
]
31+
}
4532
},
46-
// Use 'forwardPorts' to make a list of ports inside the container available locally.
47-
// "forwardPorts": [],
48-
// Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
49-
// "remoteUser": "vscode",
5033
// Make sure the files we are mapping into the container exist on the host
51-
"initializeCommand": "bash -c 'for i in $HOME/.inputrc $HOME/.bashrc_dev; do [ -f $i ] || touch $i; done'",
34+
"initializeCommand": "bash -c 'for i in $HOME/.inputrc; do [ -f $i ] || touch $i; done'",
5235
"runArgs": [
53-
"--privileged",
5436
"--net=host",
55-
"-v=${localEnv:HOME}/.ssh:/root/.ssh",
56-
"-v=${localEnv:HOME}/.bashrc_dev:/root/.bashrc",
57-
"-v=${localEnv:HOME}/.inputrc:/root/.inputrc"
37+
"--security-opt=label=type:container_runtime_t"
5838
],
5939
"mounts": [
60-
// map in home directory - not strictly necessary but may be useful
40+
"source=${localEnv:HOME}/.ssh,target=/root/.ssh,type=bind",
41+
"source=${localEnv:HOME}/.inputrc,target=/root/.inputrc,type=bind",
42+
// map in home directory - not strictly necessary but useful
6143
"source=${localEnv:HOME},target=${localEnv:HOME},type=bind,consistency=cached"
6244
],
63-
"workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind",
64-
"workspaceFolder": "/workspace",
45+
// make the workspace folder the same inside and outside of the container
46+
"workspaceMount": "source=${localWorkspaceFolder},target=${localWorkspaceFolder},type=bind",
47+
"workspaceFolder": "${localWorkspaceFolder}",
6548
// After the container is created, install the python project in editable form
66-
// This installs into the system python of the container
67-
"postCreateCommand": "pip install $([ -f requirements_dev.txt ] && echo -r requirements_dev.txt ) -e .[dev]"
49+
"postCreateCommand": "pip install -e '.[dev]'"
6850
}

.github/CONTRIBUTING.rst

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
Contributing to the project
2+
===========================
3+
4+
Contributions and issues are most welcome! All issues and pull requests are
5+
handled through GitHub_. Also, please check for any existing issues before
6+
filing a new one. If you have a great idea but it involves big changes, please
7+
file a ticket before making a pull request! We want to make sure you don't spend
8+
your time coding something that might not fit the scope of the project.
9+
10+
.. _GitHub: https://github.com/gilesknap/gphotos-sync/issues
11+
12+
Issue or Discussion?
13+
--------------------
14+
15+
Github also offers discussions_ as a place to ask questions and share ideas. If
16+
your issue is open ended and it is not obvious when it can be "closed", please
17+
raise it as a discussion instead.
18+
19+
.. _discussions: https://github.com/gilesknap/gphotos-sync/discussions
20+
21+
Code coverage
22+
-------------
23+
24+
While 100% code coverage does not make a library bug-free, it significantly
25+
reduces the number of easily caught bugs! Please make sure coverage remains the
26+
same or is improved by a pull request!
27+
28+
Developer guide
29+
---------------
30+
31+
The `Developer Guide`_ contains information on setting up a development
32+
environment, running the tests and what standards the code and documentation
33+
should follow.
34+
35+
.. _Developer Guide: https://diamondlightsource.github.io/gphotos-sync/main/developer/how-to/contribute.html
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
name: Install requirements
2+
description: Run pip install with requirements and upload resulting requirements
3+
inputs:
4+
requirements_file:
5+
description: Name of requirements file to use and upload
6+
required: true
7+
install_options:
8+
description: Parameters to pass to pip install
9+
required: true
10+
python_version:
11+
description: Python version to install
12+
default: "3.x"
13+
14+
runs:
15+
using: composite
16+
17+
steps:
18+
- name: Setup python
19+
uses: actions/setup-python@v4
20+
with:
21+
python-version: ${{ inputs.python_version }}
22+
23+
- name: Pip install
24+
run: |
25+
touch ${{ inputs.requirements_file }}
26+
# -c uses requirements.txt as constraints, see 'Validate requirements file'
27+
pip install -c ${{ inputs.requirements_file }} ${{ inputs.install_options }}
28+
shell: bash
29+
30+
- name: Create lockfile
31+
run: |
32+
mkdir -p lockfiles
33+
pip freeze --exclude-editable > lockfiles/${{ inputs.requirements_file }}
34+
# delete the self referencing line and make sure it isn't blank
35+
sed -i'' -e '/file:/d' lockfiles/${{ inputs.requirements_file }}
36+
shell: bash
37+
38+
- name: Upload lockfiles
39+
uses: actions/upload-artifact@v3
40+
with:
41+
name: lockfiles
42+
path: lockfiles
43+
44+
# This eliminates the class of problems where the requirements being given no
45+
# longer match what the packages themselves dictate. E.g. In the rare instance
46+
# where I install some-package which used to depend on vulnerable-dependency
47+
# but now uses good-dependency (despite being nominally the same version)
48+
# pip will install both if given a requirements file with -r
49+
- name: If requirements file exists, check it matches pip installed packages
50+
run: |
51+
if [ -s ${{ inputs.requirements_file }} ]; then
52+
if ! diff -u ${{ inputs.requirements_file }} lockfiles/${{ inputs.requirements_file }}; then
53+
echo "Error: ${{ inputs.requirements_file }} need the above changes to be exhaustive"
54+
exit 1
55+
fi
56+
fi
57+
shell: bash

.github/dependabot.yml

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# To get started with Dependabot version updates, you'll need to specify which
2+
# package ecosystems to update and where the package manifests are located.
3+
# Please see the documentation for all configuration options:
4+
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
5+
6+
version: 2
7+
updates:
8+
- package-ecosystem: "github-actions"
9+
directory: "/"
10+
schedule:
11+
interval: "weekly"
12+
13+
- package-ecosystem: "pip"
14+
directory: "/"
15+
schedule:
16+
interval: "weekly"

.github/pages/index.html

+5-5
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
<html>
33

44
<head>
5-
<title>Redirecting to main branch</title>
6-
<meta charset="utf-8">
7-
<meta http-equiv="refresh" content="0; url=./main/index.html">
8-
<link rel="canonical" href="main/index.html">
5+
<title>Redirecting to main branch</title>
6+
<meta charset="utf-8">
7+
<meta http-equiv="refresh" content="0; url=./main/index.html">
8+
<link rel="canonical" href="main/index.html">
99
</head>
1010

11-
</html>
11+
</html>

.github/pages/make_switcher.py

+99
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import json
2+
import logging
3+
from argparse import ArgumentParser
4+
from pathlib import Path
5+
from subprocess import CalledProcessError, check_output
6+
from typing import List, Optional
7+
8+
9+
def report_output(stdout: bytes, label: str) -> List[str]:
10+
ret = stdout.decode().strip().split("\n")
11+
print(f"{label}: {ret}")
12+
return ret
13+
14+
15+
def get_branch_contents(ref: str) -> List[str]:
16+
"""Get the list of directories in a branch."""
17+
stdout = check_output(["git", "ls-tree", "-d", "--name-only", ref])
18+
return report_output(stdout, "Branch contents")
19+
20+
21+
def get_sorted_tags_list() -> List[str]:
22+
"""Get a list of sorted tags in descending order from the repository."""
23+
stdout = check_output(["git", "tag", "-l", "--sort=-v:refname"])
24+
return report_output(stdout, "Tags list")
25+
26+
27+
def get_versions(ref: str, add: Optional[str], remove: Optional[str]) -> List[str]:
28+
"""Generate the file containing the list of all GitHub Pages builds."""
29+
# Get the directories (i.e. builds) from the GitHub Pages branch
30+
try:
31+
builds = set(get_branch_contents(ref))
32+
except CalledProcessError:
33+
builds = set()
34+
logging.warning(f"Cannot get {ref} contents")
35+
36+
# Add and remove from the list of builds
37+
if add:
38+
builds.add(add)
39+
if remove:
40+
assert remove in builds, f"Build '{remove}' not in {sorted(builds)}"
41+
builds.remove(remove)
42+
43+
# Get a sorted list of tags
44+
tags = get_sorted_tags_list()
45+
46+
# Make the sorted versions list from main branches and tags
47+
versions: List[str] = []
48+
for version in ["master", "main"] + tags:
49+
if version in builds:
50+
versions.append(version)
51+
builds.remove(version)
52+
53+
# Add in anything that is left to the bottom
54+
versions += sorted(builds)
55+
print(f"Sorted versions: {versions}")
56+
return versions
57+
58+
59+
def write_json(path: Path, repository: str, versions: str):
60+
org, repo_name = repository.split("/")
61+
struct = [
62+
{"version": version, "url": f"https://{org}.github.io/{repo_name}/{version}/"}
63+
for version in versions
64+
]
65+
text = json.dumps(struct, indent=2)
66+
print(f"JSON switcher:\n{text}")
67+
path.write_text(text, encoding="utf-8")
68+
69+
70+
def main(args=None):
71+
parser = ArgumentParser(
72+
description="Make a versions.txt file from gh-pages directories"
73+
)
74+
parser.add_argument(
75+
"--add",
76+
help="Add this directory to the list of existing directories",
77+
)
78+
parser.add_argument(
79+
"--remove",
80+
help="Remove this directory from the list of existing directories",
81+
)
82+
parser.add_argument(
83+
"repository",
84+
help="The GitHub org and repository name: ORG/REPO",
85+
)
86+
parser.add_argument(
87+
"output",
88+
type=Path,
89+
help="Path of write switcher.json to",
90+
)
91+
args = parser.parse_args(args)
92+
93+
# Write the versions file
94+
versions = get_versions("origin/gh-pages", args.add, args.remove)
95+
write_json(args.output, args.repository, versions)
96+
97+
98+
if __name__ == "__main__":
99+
main()

0 commit comments

Comments
 (0)