girder-sample-tracker 2.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- girder_sample_tracker-2.0.0/.github/workflows/release.yml +102 -0
- girder_sample_tracker-2.0.0/.gitignore +132 -0
- girder_sample_tracker-2.0.0/LICENSE +27 -0
- girder_sample_tracker-2.0.0/PKG-INFO +28 -0
- girder_sample_tracker-2.0.0/README.md +3 -0
- girder_sample_tracker-2.0.0/girder_sample_tracker/__init__.py +20 -0
- girder_sample_tracker-2.0.0/girder_sample_tracker/models/__init__.py +0 -0
- girder_sample_tracker-2.0.0/girder_sample_tracker/models/sample.py +96 -0
- girder_sample_tracker-2.0.0/girder_sample_tracker/rest/__init__.py +0 -0
- girder_sample_tracker-2.0.0/girder_sample_tracker/rest/sample.py +348 -0
- girder_sample_tracker-2.0.0/girder_sample_tracker/web_client/dist/girder-plugin-sample-tracker.umd.cjs +72 -0
- girder_sample_tracker-2.0.0/girder_sample_tracker/web_client/dist/style.css +1 -0
- girder_sample_tracker-2.0.0/girder_sample_tracker.egg-info/PKG-INFO +28 -0
- girder_sample_tracker-2.0.0/girder_sample_tracker.egg-info/SOURCES.txt +19 -0
- girder_sample_tracker-2.0.0/girder_sample_tracker.egg-info/dependency_links.txt +1 -0
- girder_sample_tracker-2.0.0/girder_sample_tracker.egg-info/entry_points.txt +2 -0
- girder_sample_tracker-2.0.0/girder_sample_tracker.egg-info/not-zip-safe +1 -0
- girder_sample_tracker-2.0.0/girder_sample_tracker.egg-info/requires.txt +3 -0
- girder_sample_tracker-2.0.0/girder_sample_tracker.egg-info/top_level.txt +1 -0
- girder_sample_tracker-2.0.0/setup.cfg +4 -0
- girder_sample_tracker-2.0.0/setup.py +30 -0
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
name: Publish Python 🐍 distribution 📦 to PyPI and TestPyPI
|
|
2
|
+
|
|
3
|
+
on: push
|
|
4
|
+
|
|
5
|
+
jobs:
|
|
6
|
+
build:
|
|
7
|
+
name: Build distribution 📦
|
|
8
|
+
runs-on: ubuntu-latest
|
|
9
|
+
|
|
10
|
+
steps:
|
|
11
|
+
- uses: actions/checkout@v4
|
|
12
|
+
- name: Set up Python
|
|
13
|
+
uses: actions/setup-python@v5
|
|
14
|
+
with:
|
|
15
|
+
python-version: "3.x"
|
|
16
|
+
- name: Set up Node.js
|
|
17
|
+
uses: actions/setup-node@v4
|
|
18
|
+
with:
|
|
19
|
+
node-version: "18"
|
|
20
|
+
- name: Install pypa/build
|
|
21
|
+
run: >-
|
|
22
|
+
python3 -m
|
|
23
|
+
pip install
|
|
24
|
+
build
|
|
25
|
+
--user
|
|
26
|
+
- name: Build js component in package/web_client
|
|
27
|
+
run: >-
|
|
28
|
+
cd $(find . -maxdepth 2 -mindepth 2 -type d -name web_client)
|
|
29
|
+
&& npm ci
|
|
30
|
+
&& npm run build
|
|
31
|
+
- name: Build a binary wheel and a source tarball
|
|
32
|
+
run: python3 -m build
|
|
33
|
+
- name: install check-manifest
|
|
34
|
+
run: >-
|
|
35
|
+
python3 -m
|
|
36
|
+
pip install
|
|
37
|
+
check-manifest
|
|
38
|
+
--user
|
|
39
|
+
- name: Check the package manifest
|
|
40
|
+
run: check-manifest -vvv
|
|
41
|
+
- name: Store the distribution packages
|
|
42
|
+
uses: actions/upload-artifact@v4
|
|
43
|
+
with:
|
|
44
|
+
name: python-package-distributions
|
|
45
|
+
path: dist/
|
|
46
|
+
|
|
47
|
+
publish-to-pypi:
|
|
48
|
+
name: >-
|
|
49
|
+
Publish Python 🐍 distribution 📦 to PyPI
|
|
50
|
+
if: startsWith(github.ref, 'refs/tags/') # only publish to PyPI on tag pushes
|
|
51
|
+
needs:
|
|
52
|
+
- build
|
|
53
|
+
runs-on: ubuntu-latest
|
|
54
|
+
environment:
|
|
55
|
+
name: pypi
|
|
56
|
+
url: https://pypi.org/p/girder-sample-tracker
|
|
57
|
+
permissions:
|
|
58
|
+
id-token: write # IMPORTANT: mandatory for trusted publishing
|
|
59
|
+
|
|
60
|
+
steps:
|
|
61
|
+
- name: Download all the dists
|
|
62
|
+
uses: actions/download-artifact@v4
|
|
63
|
+
with:
|
|
64
|
+
name: python-package-distributions
|
|
65
|
+
path: dist/
|
|
66
|
+
- name: Publish distribution 📦 to PyPI
|
|
67
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
68
|
+
|
|
69
|
+
github-release:
|
|
70
|
+
name: >-
|
|
71
|
+
Sign the Python 🐍 distribution 📦 with Sigstore
|
|
72
|
+
and upload them to GitHub Release
|
|
73
|
+
needs:
|
|
74
|
+
- publish-to-pypi
|
|
75
|
+
runs-on: ubuntu-latest
|
|
76
|
+
|
|
77
|
+
permissions:
|
|
78
|
+
contents: write # IMPORTANT: mandatory for making GitHub Releases
|
|
79
|
+
id-token: write # IMPORTANT: mandatory for sigstore
|
|
80
|
+
|
|
81
|
+
steps:
|
|
82
|
+
- name: Download all the dists
|
|
83
|
+
uses: actions/download-artifact@v4
|
|
84
|
+
with:
|
|
85
|
+
name: python-package-distributions
|
|
86
|
+
path: dist/
|
|
87
|
+
- name: Sign the dists with Sigstore
|
|
88
|
+
uses: sigstore/gh-action-sigstore-python@v3.0.0
|
|
89
|
+
with:
|
|
90
|
+
inputs: >-
|
|
91
|
+
./dist/*.tar.gz
|
|
92
|
+
./dist/*.whl
|
|
93
|
+
- name: Upload artifact signatures to GitHub Release
|
|
94
|
+
env:
|
|
95
|
+
GITHUB_TOKEN: ${{ github.token }}
|
|
96
|
+
# Upload to GitHub Release using the `gh` CLI.
|
|
97
|
+
# `dist/` contains the built packages, and the
|
|
98
|
+
# sigstore-produced signatures and certificates.
|
|
99
|
+
run: >-
|
|
100
|
+
gh release upload
|
|
101
|
+
'${{ github.ref_name }}' dist/**
|
|
102
|
+
--repo '${{ github.repository }}'
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
Testing
|
|
2
|
+
.vscode
|
|
3
|
+
|
|
4
|
+
# Byte-compiled / optimized / DLL files
|
|
5
|
+
__pycache__/
|
|
6
|
+
*.py[cod]
|
|
7
|
+
*$py.class
|
|
8
|
+
|
|
9
|
+
# C extensions
|
|
10
|
+
*.so
|
|
11
|
+
|
|
12
|
+
# Distribution / packaging
|
|
13
|
+
.Python
|
|
14
|
+
build/
|
|
15
|
+
develop-eggs/
|
|
16
|
+
dist/
|
|
17
|
+
downloads/
|
|
18
|
+
eggs/
|
|
19
|
+
.eggs/
|
|
20
|
+
parts/
|
|
21
|
+
sdist/
|
|
22
|
+
var/
|
|
23
|
+
wheels/
|
|
24
|
+
pip-wheel-metadata/
|
|
25
|
+
share/python-wheels/
|
|
26
|
+
*.egg-info/
|
|
27
|
+
.installed.cfg
|
|
28
|
+
*.egg
|
|
29
|
+
MANIFEST
|
|
30
|
+
|
|
31
|
+
# PyInstaller
|
|
32
|
+
# Usually these files are written by a python script from a template
|
|
33
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
34
|
+
*.manifest
|
|
35
|
+
*.spec
|
|
36
|
+
|
|
37
|
+
# Installer logs
|
|
38
|
+
pip-log.txt
|
|
39
|
+
pip-delete-this-directory.txt
|
|
40
|
+
|
|
41
|
+
# Unit test / coverage reports
|
|
42
|
+
htmlcov/
|
|
43
|
+
.tox/
|
|
44
|
+
.nox/
|
|
45
|
+
.coverage
|
|
46
|
+
.coverage.*
|
|
47
|
+
.cache
|
|
48
|
+
nosetests.xml
|
|
49
|
+
coverage.xml
|
|
50
|
+
*.cover
|
|
51
|
+
*.py,cover
|
|
52
|
+
.hypothesis/
|
|
53
|
+
.pytest_cache/
|
|
54
|
+
|
|
55
|
+
# Translations
|
|
56
|
+
*.mo
|
|
57
|
+
*.pot
|
|
58
|
+
|
|
59
|
+
# Django stuff:
|
|
60
|
+
*.log
|
|
61
|
+
local_settings.py
|
|
62
|
+
db.sqlite3
|
|
63
|
+
db.sqlite3-journal
|
|
64
|
+
|
|
65
|
+
# Flask stuff:
|
|
66
|
+
instance/
|
|
67
|
+
.webassets-cache
|
|
68
|
+
|
|
69
|
+
# Scrapy stuff:
|
|
70
|
+
.scrapy
|
|
71
|
+
|
|
72
|
+
# Sphinx documentation
|
|
73
|
+
docs/_build/
|
|
74
|
+
|
|
75
|
+
# PyBuilder
|
|
76
|
+
target/
|
|
77
|
+
|
|
78
|
+
# Jupyter Notebook
|
|
79
|
+
.ipynb_checkpoints
|
|
80
|
+
|
|
81
|
+
# IPython
|
|
82
|
+
profile_default/
|
|
83
|
+
ipython_config.py
|
|
84
|
+
|
|
85
|
+
# pyenv
|
|
86
|
+
.python-version
|
|
87
|
+
|
|
88
|
+
# pipenv
|
|
89
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
90
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
91
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
92
|
+
# install all needed dependencies.
|
|
93
|
+
#Pipfile.lock
|
|
94
|
+
|
|
95
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
|
96
|
+
__pypackages__/
|
|
97
|
+
|
|
98
|
+
# Celery stuff
|
|
99
|
+
celerybeat-schedule
|
|
100
|
+
celerybeat.pid
|
|
101
|
+
|
|
102
|
+
# SageMath parsed files
|
|
103
|
+
*.sage.py
|
|
104
|
+
|
|
105
|
+
# Environments
|
|
106
|
+
.env
|
|
107
|
+
.venv
|
|
108
|
+
env/
|
|
109
|
+
venv/
|
|
110
|
+
ENV/
|
|
111
|
+
env.bak/
|
|
112
|
+
venv.bak/
|
|
113
|
+
|
|
114
|
+
# Spyder project settings
|
|
115
|
+
.spyderproject
|
|
116
|
+
.spyproject
|
|
117
|
+
|
|
118
|
+
# Rope project settings
|
|
119
|
+
.ropeproject
|
|
120
|
+
|
|
121
|
+
# mkdocs documentation
|
|
122
|
+
/site
|
|
123
|
+
|
|
124
|
+
# mypy
|
|
125
|
+
.mypy_cache/
|
|
126
|
+
.dmypy.json
|
|
127
|
+
dmypy.json
|
|
128
|
+
|
|
129
|
+
# Pyre type checker
|
|
130
|
+
.pyre/
|
|
131
|
+
|
|
132
|
+
node_modules/
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
Copyright (c) 2024, Kacper Kowalik, University of Illinois at Urbana-Champaign
|
|
2
|
+
All rights reserved.
|
|
3
|
+
|
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
|
5
|
+
modification, are permitted provided that the following conditions are met:
|
|
6
|
+
|
|
7
|
+
* Redistributions of source code must retain the above copyright notice, this
|
|
8
|
+
list of conditions and the following disclaimer.
|
|
9
|
+
|
|
10
|
+
* Redistributions in binary form must reproduce the above copyright notice,
|
|
11
|
+
this list of conditions and the following disclaimer in the documentation
|
|
12
|
+
and/or other materials provided with the distribution.
|
|
13
|
+
|
|
14
|
+
* Neither the name of girder_wholetale nor the names of its
|
|
15
|
+
contributors may be used to endorse or promote products derived from
|
|
16
|
+
this software without specific prior written permission.
|
|
17
|
+
|
|
18
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
19
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
20
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
21
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
22
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
23
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
24
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
25
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
26
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
27
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: girder-sample-tracker
|
|
3
|
+
Version: 2.0.0
|
|
4
|
+
Summary: Girder Plugin adding a simple tracker for material samples
|
|
5
|
+
License: BSD
|
|
6
|
+
Classifier: Development Status :: 4 - Beta
|
|
7
|
+
Classifier: Environment :: Web Environment
|
|
8
|
+
Classifier: License :: OSI Approved :: BSD License
|
|
9
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
10
|
+
Classifier: Programming Language :: Python
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Requires-Python: >=3.10
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
License-File: LICENSE
|
|
15
|
+
Requires-Dist: girder>=5.0.0a5.dev0
|
|
16
|
+
Requires-Dist: qrcode[pil]
|
|
17
|
+
Requires-Dist: cairosvg
|
|
18
|
+
Dynamic: classifier
|
|
19
|
+
Dynamic: description
|
|
20
|
+
Dynamic: description-content-type
|
|
21
|
+
Dynamic: license
|
|
22
|
+
Dynamic: requires-dist
|
|
23
|
+
Dynamic: requires-python
|
|
24
|
+
Dynamic: summary
|
|
25
|
+
|
|
26
|
+
### Girder Sample Tracker
|
|
27
|
+
|
|
28
|
+
This plugin provides a simple tracker for material samples. It is intended to be used in conjunction with the [Girder](https://girder.readthedocs.io/en/latest/) data management platform.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from girder.plugin import GirderPlugin, registerPluginStaticContent
|
|
3
|
+
from girder.utility.model_importer import ModelImporter
|
|
4
|
+
from .rest.sample import Sample
|
|
5
|
+
from .models.sample import Sample as SampleModel
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class SampleTrackerPlugin(GirderPlugin):
|
|
9
|
+
DISPLAY_NAME = "Sample Tracker"
|
|
10
|
+
|
|
11
|
+
def load(self, info):
|
|
12
|
+
ModelImporter.registerModel("sample", SampleModel, plugin="sample_tracker")
|
|
13
|
+
info["apiRoot"].sample = Sample()
|
|
14
|
+
registerPluginStaticContent(
|
|
15
|
+
plugin="sample_tracker",
|
|
16
|
+
css=["/style.css"],
|
|
17
|
+
js=["/girder-plugin-sample-tracker.umd.cjs"],
|
|
18
|
+
staticDir=os.path.join(os.path.dirname(__file__), "web_client", "dist"),
|
|
19
|
+
tree=info["serverRoot"],
|
|
20
|
+
)
|
|
File without changes
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import datetime
|
|
2
|
+
import io
|
|
3
|
+
|
|
4
|
+
import cairosvg
|
|
5
|
+
import qrcode
|
|
6
|
+
from girder.constants import AccessType
|
|
7
|
+
from girder.models.model_base import AccessControlledModel
|
|
8
|
+
from qrcode.compat.etree import ET
|
|
9
|
+
from qrcode.image.svg import SvgPathFillImage
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Sample(AccessControlledModel):
|
|
13
|
+
def initialize(self):
|
|
14
|
+
self.name = "sample"
|
|
15
|
+
self.ensureIndices(["name"])
|
|
16
|
+
|
|
17
|
+
self.exposeFields(
|
|
18
|
+
level=AccessType.READ,
|
|
19
|
+
fields=(
|
|
20
|
+
"_id",
|
|
21
|
+
"created",
|
|
22
|
+
"creator",
|
|
23
|
+
"description",
|
|
24
|
+
"eventTypes",
|
|
25
|
+
"updated",
|
|
26
|
+
"name",
|
|
27
|
+
"events",
|
|
28
|
+
),
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
def validate(self, doc):
|
|
32
|
+
return doc
|
|
33
|
+
|
|
34
|
+
def create(
|
|
35
|
+
self, name, creator, description=None, eventTypes=None, access=None, save=True
|
|
36
|
+
):
|
|
37
|
+
now = datetime.datetime.utcnow()
|
|
38
|
+
|
|
39
|
+
sample = {
|
|
40
|
+
"name": name,
|
|
41
|
+
"creator": creator["_id"],
|
|
42
|
+
"created": now,
|
|
43
|
+
"description": description,
|
|
44
|
+
"eventTypes": eventTypes or [],
|
|
45
|
+
"updated": now,
|
|
46
|
+
"events": [],
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if access is not None:
|
|
50
|
+
self.setAccessList(sample, access, save=False, user=creator)
|
|
51
|
+
else:
|
|
52
|
+
self.setUserAccess(sample, user=creator, level=AccessType.ADMIN, save=False)
|
|
53
|
+
if save:
|
|
54
|
+
sample = self.save(sample)
|
|
55
|
+
|
|
56
|
+
return sample
|
|
57
|
+
|
|
58
|
+
def add_event(self, sample, event, save=True):
|
|
59
|
+
sample["events"].insert(0, event)
|
|
60
|
+
sample["updated"] = event["created"]
|
|
61
|
+
|
|
62
|
+
if save:
|
|
63
|
+
sample = self.save(sample)
|
|
64
|
+
|
|
65
|
+
return sample
|
|
66
|
+
|
|
67
|
+
def qr_code(self, sample, url):
|
|
68
|
+
buf = io.BytesIO()
|
|
69
|
+
qr = qrcode.QRCode(
|
|
70
|
+
version=6,
|
|
71
|
+
error_correction=qrcode.constants.ERROR_CORRECT_H,
|
|
72
|
+
border=10,
|
|
73
|
+
image_factory=SvgPathFillImage,
|
|
74
|
+
)
|
|
75
|
+
qr.add_data(f"{url}/#sample/{sample['_id']}/add")
|
|
76
|
+
qr.make(fit=True)
|
|
77
|
+
|
|
78
|
+
img = qr.make_image(fill_color="black", back_color="white")
|
|
79
|
+
text = ET.SubElement(
|
|
80
|
+
img._img,
|
|
81
|
+
"text",
|
|
82
|
+
{
|
|
83
|
+
"x": "50%",
|
|
84
|
+
"y": "93%",
|
|
85
|
+
"dominant-baseline": "middle",
|
|
86
|
+
"text-anchor": "middle",
|
|
87
|
+
"font-size": "5",
|
|
88
|
+
"fill": "black",
|
|
89
|
+
},
|
|
90
|
+
)
|
|
91
|
+
text.text = sample["name"]
|
|
92
|
+
cairosvg.svg2png(
|
|
93
|
+
bytestring=img.to_string(encoding="unicode"), write_to=buf, dpi=300
|
|
94
|
+
)
|
|
95
|
+
buf.seek(0)
|
|
96
|
+
return buf
|
|
File without changes
|