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.
@@ -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,3 @@
1
+ ### Girder Sample Tracker
2
+
3
+ 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
+ )
@@ -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