bec-launcher 0.1.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,41 @@
1
+ name: Bug report
2
+ description: File a bug report.
3
+ title: "[BUG]: "
4
+ labels: ["bug"]
5
+
6
+ body:
7
+ - type: markdown
8
+ attributes:
9
+ value: |
10
+ Bug report:
11
+ - type: textarea
12
+ id: description
13
+ attributes:
14
+ label: Provide a brief description of the bug.
15
+ - type: textarea
16
+ id: expected
17
+ attributes:
18
+ label: Describe what you expected to happen and what actually happened.
19
+ - type: textarea
20
+ id: reproduction
21
+ attributes:
22
+ label: Outline the steps that lead to the bug's occurrence. Be specific and provide a clear sequence of actions.
23
+ - type: input
24
+ id: version
25
+ attributes:
26
+ label: bec_widgets version
27
+ description: which version of BEC widgets was running?
28
+ - type: input
29
+ id: bec-version
30
+ attributes:
31
+ label: bec core version
32
+ description: which version of BEC core was running?
33
+ - type: textarea
34
+ id: extra
35
+ attributes:
36
+ label: Any extra info / data? e.g. log output...
37
+ - type: input
38
+ id: issues
39
+ attributes:
40
+ label: Related issues
41
+ description: please tag any related issues
@@ -0,0 +1,37 @@
1
+ ---
2
+ name: Documentation update request
3
+ about: Suggest an update to the docs
4
+ title: '[DOCS]: '
5
+ type: documentation
6
+ label: documentation
7
+ assignees: ''
8
+
9
+ ---
10
+
11
+ ## Documentation Section
12
+
13
+ [Specify the section or page of the documentation that needs updating]
14
+
15
+ ## Current Information
16
+
17
+ [Provide the current information in the documentation that needs to be updated]
18
+
19
+ ## Proposed Update
20
+
21
+ [Describe the proposed update or correction. Be specific about the changes that need to be made]
22
+
23
+ ## Reason for Update
24
+
25
+ [Explain the reason for the documentation update. Include any recent changes, new features, or corrections that necessitate the update]
26
+
27
+ ## Additional Context
28
+
29
+ [Include any additional context or information that can help the documentation team understand the update better]
30
+
31
+ ## Attachments
32
+
33
+ [Attach any files, screenshots, or references that can assist in making the documentation update]
34
+
35
+ ## Priority
36
+
37
+ [Assign a priority level to the documentation update based on its urgency. Use a scale such as Low, Medium, High]
@@ -0,0 +1,49 @@
1
+ ---
2
+ name: Feature request
3
+ about: Suggest an idea for this project
4
+ title: '[FEAT]: '
5
+ type: feature
6
+ label: feature
7
+ assignees: ''
8
+
9
+ ---
10
+
11
+ ## Feature Summary
12
+
13
+ [Provide a brief and clear summary of the new feature you are requesting]
14
+
15
+ ## Problem Description
16
+
17
+ [Explain the problem or need that this feature aims to address. Be specific about the issues or gaps in the current functionality]
18
+
19
+ ## Use Case
20
+
21
+ [Describe a real-world scenario or use case where this feature would be beneficial. Explain how it would improve the user experience or workflow]
22
+
23
+ ## Proposed Solution
24
+
25
+ [If you have a specific solution in mind, describe it here. Explain how it would work and how it would address the problem described above]
26
+
27
+ ## Benefits
28
+
29
+ [Explain the benefits and advantages of implementing this feature. Highlight how it adds value to the product or improves user satisfaction]
30
+
31
+ ## Alternatives Considered
32
+
33
+ [If you've considered alternative solutions or workarounds, mention them here. Explain why the proposed feature is the preferred option]
34
+
35
+ ## Impact on Existing Functionality
36
+
37
+ [Discuss how the new feature might impact or interact with existing features. Address any potential conflicts or dependencies]
38
+
39
+ ## Priority
40
+
41
+ [Assign a priority level to the feature request based on its importance. Use a scale such as Low, Medium, High]
42
+
43
+ ## Attachments
44
+
45
+ [Include any relevant attachments, such as sketches, diagrams, or references that can help the development team understand your feature request better]
46
+
47
+ ## Additional Information
48
+
49
+ [Provide any additional information that might be relevant to the feature request, such as user feedback, market trends, or similar features in other products]
@@ -0,0 +1,33 @@
1
+ ## Description
2
+
3
+ [Provide a brief description of the changes introduced by this pull request.]
4
+
5
+ ## Related Issues
6
+
7
+ [Cite any related issues or feature requests that are addressed or resolved by this pull request. Link the associated issue, for example, with `fixes #123` or `closes #123`.]
8
+
9
+ ## Type of Change
10
+
11
+ - Change 1
12
+ - Change 2
13
+
14
+ ## How to test
15
+
16
+ - Run unit tests
17
+ - Open [widget] in designer and play around with the properties
18
+
19
+ ## Potential side effects
20
+
21
+ [Describe any potential side effects or risks of merging this PR.]
22
+
23
+ ## Screenshots / GIFs (if applicable)
24
+
25
+ [Include any relevant screenshots or GIFs to showcase the changes made.]
26
+
27
+ ## Additional Comments
28
+
29
+ [Add any additional comments or information that may be helpful for reviewers.]
30
+
31
+ ## Definition of Done
32
+ - [ ] Documentation is up-to-date.
33
+
@@ -0,0 +1,32 @@
1
+ name: "BEC Launcher Install"
2
+ description: "Install BEC Launcher and related os dependencies"
3
+ inputs:
4
+ BEC_LAUNCHER_BRANCH: # id of input
5
+ required: false
6
+ default: "main"
7
+ description: "Branch of BEC Launcher to install"
8
+ PYTHON_VERSION: # id of input
9
+ required: false
10
+ default: "3.11"
11
+ description: "Python version to use"
12
+
13
+ runs:
14
+ using: "composite"
15
+ steps:
16
+ - name: Setup Python
17
+ uses: actions/setup-python@v5
18
+ with:
19
+ python-version: ${{ inputs.PYTHON_VERSION }}
20
+
21
+ - name: Checkout BEC Core
22
+ uses: actions/checkout@v4
23
+ with:
24
+ repository: bec-project/bec_launcher
25
+ ref: ${{ inputs.BEC_LAUNCHER_BRANCH }}
26
+ path: ./bec_launcher
27
+
28
+ - name: Install Python dependencies
29
+ shell: bash
30
+ run: |
31
+ pip install uv
32
+ uv pip install --system -e ./bec_launcher[dev]
@@ -0,0 +1,16 @@
1
+ name: Add issues to the BEC project
2
+
3
+ on:
4
+ issues:
5
+ types:
6
+ - opened
7
+
8
+ jobs:
9
+ add-to-project:
10
+ name: Add issue to project
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/add-to-project@v1.0.2
14
+ with:
15
+ project-url: https://github.com/orgs/bec-project/projects/3
16
+ github-token: ${{ secrets.ADD_ISSUE_TO_PROJECT }}
@@ -0,0 +1,28 @@
1
+ name: Check PR status for branch
2
+ on:
3
+ workflow_call:
4
+ outputs:
5
+ branch-pr:
6
+ description: The PR number if the branch is in one
7
+ value: ${{ jobs.pr.outputs.branch-pr }}
8
+
9
+ jobs:
10
+ pr:
11
+ runs-on: "ubuntu-latest"
12
+ outputs:
13
+ branch-pr: ${{ steps.script.outputs.result }}
14
+ steps:
15
+ - uses: actions/github-script@v7
16
+ id: script
17
+ if: github.event_name == 'push' && github.event.ref_type != 'tag'
18
+ with:
19
+ script: |
20
+ const prs = await github.rest.pulls.list({
21
+ owner: context.repo.owner,
22
+ repo: context.repo.repo,
23
+ head: context.repo.owner + ':${{ github.ref_name }}'
24
+ })
25
+ if (prs.data.length) {
26
+ console.log(`::notice ::Skipping CI on branch push as it is already run in PR #${prs.data[0]["number"]}`)
27
+ return prs.data[0]["number"]
28
+ }
@@ -0,0 +1,38 @@
1
+ name: Full CI
2
+ on:
3
+ push:
4
+ pull_request:
5
+ workflow_dispatch:
6
+ inputs:
7
+ BEC_LAUNCHER_BRANCH:
8
+ description: "Branch of BEC Launcher to install"
9
+ required: false
10
+ type: string
11
+
12
+ permissions:
13
+ pull-requests: write
14
+
15
+ jobs:
16
+ check_pr_status:
17
+ uses: ./.github/workflows/check_pr.yml
18
+
19
+ formatter:
20
+ needs: check_pr_status
21
+ if: needs.check_pr_status.outputs.branch-pr == ''
22
+ uses: ./.github/workflows/formatter.yml
23
+
24
+ unit-test:
25
+ needs: [check_pr_status, formatter]
26
+ if: needs.check_pr_status.outputs.branch-pr == ''
27
+ uses: ./.github/workflows/pytest.yml
28
+ with:
29
+ BEC_LAUNCHER_BRANCH: ${{ inputs.BEC_LAUNCHER_BRANCH || 'main' }}
30
+ secrets:
31
+ CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
32
+
33
+ unit-test-matrix:
34
+ needs: [check_pr_status, formatter]
35
+ if: needs.check_pr_status.outputs.branch-pr == ''
36
+ uses: ./.github/workflows/pytest-matrix.yml
37
+ with:
38
+ BEC_LAUNCHER_BRANCH: ${{ inputs.BEC_LAUNCHER_BRANCH || 'main' }}
@@ -0,0 +1,61 @@
1
+ name: Formatter and Pylint jobs
2
+ on: [workflow_call]
3
+ jobs:
4
+
5
+ Formatter:
6
+ runs-on: ubuntu-latest
7
+ steps:
8
+ - name: Check out repository code
9
+ uses: actions/checkout@v4
10
+ - name: Set up Python
11
+ uses: actions/setup-python@v5
12
+ with:
13
+ python-version: '3.13'
14
+
15
+ - name: Run black and isort
16
+ run: |
17
+ pip install black isort
18
+ pip install -e .[dev]
19
+ black --check --diff --color .
20
+ isort --check --diff ./
21
+ Pylint:
22
+ runs-on: ubuntu-latest
23
+
24
+ steps:
25
+ - uses: actions/checkout@v4
26
+
27
+ - name: Set up Python
28
+ uses: actions/setup-python@v5
29
+ with:
30
+ python-version: '3.13'
31
+
32
+ - name: Install dependencies
33
+ run: |
34
+ python -m pip install --upgrade pip
35
+ pip install pylint pylint-exit anybadge
36
+
37
+ - name: Run Pylint
38
+ run: |
39
+ mkdir -p ./pylint
40
+ set +e
41
+ pylint ./${{ github.event.repository.name }} --output-format=text > ./pylint/pylint.log
42
+ pylint-exit $?
43
+ set -e
44
+
45
+ - name: Extract Pylint Score
46
+ id: score
47
+ run: |
48
+ SCORE=$(sed -n 's/^Your code has been rated at \([-0-9.]*\)\/.*/\1/p' ./pylint/pylint.log)
49
+ echo "score=$SCORE" >> $GITHUB_OUTPUT
50
+
51
+ - name: Create Badge
52
+ run: |
53
+ anybadge --label=Pylint --file=./pylint/pylint.svg --value="${{ steps.score.outputs.score }}" 2=red 4=orange 8=yellow 10=green
54
+
55
+ - name: Upload Artifacts
56
+ uses: actions/upload-artifact@v4
57
+ with:
58
+ name: pylint-artifacts
59
+ path: |
60
+ # ./pylint/pylint.log # not sure why this isn't working
61
+ ./pylint/pylint.svg
@@ -0,0 +1,35 @@
1
+ name: Run Pytest with different Python versions
2
+ on:
3
+ workflow_call:
4
+ inputs:
5
+ BEC_LAUNCHER_BRANCH:
6
+ description: "Branch of BEC Launcher to install"
7
+ required: false
8
+ default: "main"
9
+ type: string
10
+
11
+ jobs:
12
+ pytest-matrix:
13
+ runs-on: ubuntu-latest
14
+ strategy:
15
+ matrix:
16
+ python-version: ["3.11", "3.12", "3.13"]
17
+
18
+ steps:
19
+ - name: Checkout BEC Launcher
20
+ uses: actions/checkout@v4
21
+ with:
22
+ repository: bec-project/bec_launcher
23
+ ref: ${{ inputs.BEC_LAUNCHER_BRANCH }}
24
+
25
+ - name: Install BEC Launcher and dependencies
26
+ uses: ./.github/actions/bec_launcher_install
27
+ with:
28
+ BEC_LAUNCHER_BRANCH: ${{ inputs.BEC_LAUNCHER_BRANCH }}
29
+ PYTHON_VERSION: ${{ matrix.python-version }}
30
+
31
+ - name: Run Pytest
32
+ run: |
33
+ cd ./bec_launcher
34
+ pip install pytest pytest-random-order
35
+ pytest -v --maxfail=2 --junitxml=report.xml --random-order ./tests
@@ -0,0 +1,46 @@
1
+ name: Run Pytest with Coverage
2
+ on:
3
+ workflow_call:
4
+ inputs:
5
+ BEC_LAUNCHER_BRANCH:
6
+ description: "Branch of BEC Launcher to install"
7
+ required: false
8
+ default: "main"
9
+ type: string
10
+ secrets:
11
+ CODECOV_TOKEN:
12
+ required: true
13
+
14
+ permissions:
15
+ pull-requests: write
16
+
17
+ jobs:
18
+ pytest:
19
+ runs-on: ubuntu-latest
20
+
21
+ steps:
22
+ - name: Checkout BEC Launcher
23
+ uses: actions/checkout@v4
24
+ with:
25
+ repository: bec-project/bec_launcher
26
+ ref: ${{ inputs.BEC_LAUNCHER_BRANCH }}
27
+
28
+ - name: Install BEC Launcher and dependencies
29
+ uses: ./.github/actions/bec_launcher_install
30
+ with:
31
+ BEC_LAUNCHER_BRANCH: ${{ inputs.BEC_LAUNCHER_BRANCH }}
32
+ PYTHON_VERSION: 3.11
33
+
34
+ - name: Run Pytest with Coverage
35
+ id: coverage
36
+ run: |
37
+ cd ./bec_launcher
38
+ coverage run --source=./bec_launcher --omit=*/bec_launcher/tests/* -m pytest -v --junitxml=report.xml --random-order --full-trace ./tests
39
+ coverage report
40
+ coverage xml
41
+
42
+ - name: Upload coverage to Codecov
43
+ uses: codecov/codecov-action@v5
44
+ with:
45
+ token: ${{ secrets.CODECOV_TOKEN }}
46
+ slug: bec-project/bec_launcher
@@ -0,0 +1,95 @@
1
+ name: Continuous Delivery
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+
8
+ # default: least privileged permissions across all jobs
9
+ permissions:
10
+ contents: read
11
+
12
+
13
+
14
+ jobs:
15
+ release:
16
+ runs-on: ubuntu-latest
17
+ concurrency:
18
+ group: ${{ github.workflow }}-release-${{ github.ref_name }}
19
+ cancel-in-progress: false
20
+
21
+ permissions:
22
+ contents: write
23
+
24
+ steps:
25
+ # Note: We checkout the repository at the branch that triggered the workflow
26
+ # with the entire history to ensure to match PSR's release branch detection
27
+ # and history evaluation.
28
+ # However, we forcefully reset the branch to the workflow sha because it is
29
+ # possible that the branch was updated while the workflow was running. This
30
+ # prevents accidentally releasing un-evaluated changes.
31
+ - name: Setup | Checkout Repository on Release Branch
32
+ uses: actions/checkout@v4
33
+ with:
34
+ ref: ${{ github.ref_name }}
35
+ fetch-depth: 0
36
+ ssh-key: ${{ secrets.CI_DEPLOY_SSH_KEY }}
37
+ ssh-known-hosts: ${{ secrets.CI_DEPLOY_SSH_KNOWN_HOSTS }}
38
+
39
+ - name: Set up Python
40
+ uses: actions/setup-python@v5
41
+ with:
42
+ python-version: '3.11'
43
+
44
+ - name: Setup | Force release branch to be at workflow sha
45
+ run: |
46
+ git reset --hard ${{ github.sha }}
47
+ - name: Evaluate | Verify upstream has NOT changed
48
+ # Last chance to abort before causing an error as another PR/push was applied to
49
+ # the upstream branch while this workflow was running. This is important
50
+ # because we are committing a version change (--commit). You may omit this step
51
+ # if you have 'commit: false' in your configuration.
52
+ #
53
+ # You may consider moving this to a repo script and call it from this step instead
54
+ # of writing it in-line.
55
+ shell: bash
56
+ run: |
57
+ set +o pipefail
58
+
59
+ UPSTREAM_BRANCH_NAME="$(git status -sb | head -n 1 | cut -d' ' -f2 | grep -E '\.{3}' | cut -d'.' -f4)"
60
+ printf '%s\n' "Upstream branch name: $UPSTREAM_BRANCH_NAME"
61
+
62
+ set -o pipefail
63
+
64
+ if [ -z "$UPSTREAM_BRANCH_NAME" ]; then
65
+ printf >&2 '%s\n' "::error::Unable to determine upstream branch name!"
66
+ exit 1
67
+ fi
68
+
69
+ git fetch "${UPSTREAM_BRANCH_NAME%%/*}"
70
+
71
+ if ! UPSTREAM_SHA="$(git rev-parse "$UPSTREAM_BRANCH_NAME")"; then
72
+ printf >&2 '%s\n' "::error::Unable to determine upstream branch sha!"
73
+ exit 1
74
+ fi
75
+
76
+ HEAD_SHA="$(git rev-parse HEAD)"
77
+
78
+ if [ "$HEAD_SHA" != "$UPSTREAM_SHA" ]; then
79
+ printf >&2 '%s\n' "[HEAD SHA] $HEAD_SHA != $UPSTREAM_SHA [UPSTREAM SHA]"
80
+ printf >&2 '%s\n' "::error::Upstream has changed, aborting release..."
81
+ exit 1
82
+ fi
83
+
84
+ printf '%s\n' "Verified upstream branch has not changed, continuing with release..."
85
+
86
+ - name: Semantic Version Release
87
+ id: release
88
+ env:
89
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
90
+ run: |
91
+ pip install python-semantic-release==9.* wheel build twine
92
+ semantic-release -vv version
93
+ if [ ! -d dist ]; then echo No release will be made; exit 0; fi
94
+ twine upload dist/* -u __token__ -p ${{ secrets.CI_PYPI_TOKEN }} --skip-existing
95
+ semantic-release publish
@@ -0,0 +1,35 @@
1
+ name: Sync PR to Project
2
+
3
+ on:
4
+ pull_request:
5
+ types:
6
+ [
7
+ opened,
8
+ assigned,
9
+ unassigned,
10
+ edited,
11
+ ready_for_review,
12
+ converted_to_draft,
13
+ reopened,
14
+ synchronize,
15
+ closed,
16
+ ]
17
+
18
+ jobs:
19
+ sync-project:
20
+ runs-on: ubuntu-latest
21
+
22
+ permissions:
23
+ issues: write
24
+ pull-requests: read
25
+ contents: read
26
+
27
+ steps:
28
+ - name: Sync PR to Project
29
+ uses: bec-project/action-issue-sync-pr@v1
30
+ with:
31
+ token: ${{ secrets.ADD_ISSUE_TO_PROJECT }}
32
+ org: ${{ github.repository_owner }}
33
+ repo: ${{ github.repository }}
34
+ project-number: 3
35
+ pr-number: ${{ github.event.pull_request.number }}
@@ -0,0 +1,180 @@
1
+ **/*_venv
2
+ **/.idea
3
+ *.log
4
+ **/__pycache__
5
+ **/.DS_Store
6
+ **/out
7
+ **/.vscode
8
+ **/.pytest_cache
9
+ **/*.egg*
10
+
11
+ # file writer data
12
+ **.h5
13
+
14
+ # ignore recover_config files
15
+ recovery_config*
16
+
17
+ # Byte-compiled / optimized / DLL files
18
+ __pycache__/
19
+ *.py[cod]
20
+ *$py.class
21
+
22
+ # C extensions
23
+ *.so
24
+
25
+ # Distribution / packaging
26
+ .Python
27
+ build/
28
+ develop-eggs/
29
+ dist/
30
+ downloads/
31
+ eggs/
32
+ .eggs/
33
+ lib/
34
+ lib64/
35
+ parts/
36
+ sdist/
37
+ var/
38
+ wheels/
39
+ share/python-wheels/
40
+ *.egg-info/
41
+ .installed.cfg
42
+ *.egg
43
+ MANIFEST
44
+
45
+ # PyInstaller
46
+ # Usually these files are written by a python script from a template
47
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
48
+ *.manifest
49
+ *.spec
50
+
51
+ # Installer logs
52
+ pip-log.txt
53
+ pip-delete-this-directory.txt
54
+
55
+ # Unit test / coverage reports
56
+ htmlcov/
57
+ .tox/
58
+ .nox/
59
+ .coverage
60
+ .coverage.*
61
+ .cache
62
+ nosetests.xml
63
+ coverage.xml
64
+ *.cover
65
+ *.py,cover
66
+ .hypothesis/
67
+ .pytest_cache/
68
+ cover/
69
+
70
+ # Translations
71
+ *.mo
72
+ *.pot
73
+
74
+ # Django stuff:
75
+ *.log
76
+ local_settings.py
77
+ db.sqlite3
78
+ db.sqlite3-journal
79
+
80
+ # Flask stuff:
81
+ instance/
82
+ .webassets-cache
83
+
84
+ # Scrapy stuff:
85
+ .scrapy
86
+
87
+ # Sphinx documentation
88
+ docs/**/_build/
89
+ docs/**/autodoc/
90
+ docs/**/_autosummary/
91
+
92
+ # PyBuilder
93
+ .pybuilder/
94
+ target/
95
+
96
+ # Jupyter Notebook
97
+ .ipynb_checkpoints
98
+
99
+ # IPython
100
+ profile_default/
101
+ ipython_config.py
102
+
103
+ **.prof
104
+
105
+ # pyenv
106
+ # For a library or package, you might want to ignore these files since the code is
107
+ # intended to run in multiple environments; otherwise, check them in:
108
+ # .python-version
109
+
110
+ # pipenv
111
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
112
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
113
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
114
+ # install all needed dependencies.
115
+ #Pipfile.lock
116
+
117
+ # poetry
118
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
119
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
120
+ # commonly ignored for libraries.
121
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
122
+ #poetry.lock
123
+
124
+ # pdm
125
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
126
+ #pdm.lock
127
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
128
+ # in version control.
129
+ # https://pdm.fming.dev/#use-with-ide
130
+ .pdm.toml
131
+
132
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
133
+ __pypackages__/
134
+
135
+ # Celery stuff
136
+ celerybeat-schedule
137
+ celerybeat.pid
138
+
139
+ # SageMath parsed files
140
+ *.sage.py
141
+
142
+ # Environments
143
+ .env
144
+ .venv
145
+ env/
146
+ venv/
147
+ ENV/
148
+ env.bak/
149
+ venv.bak/
150
+
151
+ # Spyder project settings
152
+ .spyderproject
153
+ .spyproject
154
+
155
+ # Rope project settings
156
+ .ropeproject
157
+
158
+ # mkdocs documentation
159
+ /site
160
+
161
+ # mypy
162
+ .mypy_cache/
163
+ .dmypy.json
164
+ dmypy.json
165
+
166
+ # Pyre type checker
167
+ .pyre/
168
+
169
+ # pytype static type analyzer
170
+ .pytype/
171
+
172
+ # Cython debug symbols
173
+ cython_debug/
174
+
175
+ # PyCharm
176
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
177
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
178
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
179
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
180
+ #.idea/
@@ -0,0 +1,14 @@
1
+ # CHANGELOG
2
+
3
+
4
+ ## v0.1.0 (2026-01-09)
5
+
6
+ ### Features
7
+
8
+ - Simple launch file to demonstrate usage
9
+ ([`4ee8761`](https://github.com/bec-project/bec_launcher/commit/4ee87619a2dad87a8cd6bd2a28bc3f8b7b05af14))
10
+
11
+ ### Refactoring
12
+
13
+ - Enhance type safety by introducing DeploymentDict for deployment names
14
+ ([`47e47da`](https://github.com/bec-project/bec_launcher/commit/47e47dac3cf3aaab5084bc4e32fbd194bf55f54d))
@@ -0,0 +1,29 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2026, Paul Scherrer Institut
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
8
+
9
+ 1. Redistributions of source code must retain the above copyright notice, this
10
+ list of conditions and the following disclaimer.
11
+
12
+ 2. Redistributions in binary form must reproduce the above copyright notice,
13
+ this list of conditions and the following disclaimer in the documentation
14
+ and/or other materials provided with the distribution.
15
+
16
+ 3. Neither the name of the copyright holder nor the names of its
17
+ contributors may be used to endorse or promote products derived from
18
+ this software without specific prior written permission.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,20 @@
1
+ Metadata-Version: 2.4
2
+ Name: bec_launcher
3
+ Version: 0.1.0
4
+ Summary: BEC Launcher: A launcher application for BEC clients and tools.
5
+ Project-URL: Bug Tracker, https://github.com/bec-project/bec_launcher/issues
6
+ Project-URL: Homepage, https://github.com/bec-project/bec_launcher
7
+ Project-URL: documentation, https://bec.readthedocs.org
8
+ Project-URL: changelog, https://github.com/bec-project/bec_launcher/blob/main/CHANGELOG.md
9
+ License-File: LICENSE
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Topic :: Scientific/Engineering
13
+ Requires-Python: >=3.11
14
+ Provides-Extra: dev
15
+ Requires-Dist: black~=25.0; extra == 'dev'
16
+ Requires-Dist: coverage~=7.0; extra == 'dev'
17
+ Requires-Dist: isort>=5.13.2,~=5.13; extra == 'dev'
18
+ Requires-Dist: pylint~=3.0; extra == 'dev'
19
+ Requires-Dist: pytest-random-order~=1.1; extra == 'dev'
20
+ Requires-Dist: pytest~=8.0; extra == 'dev'
@@ -0,0 +1,15 @@
1
+ # BEC Launcher
2
+
3
+ A launcher application for BEC clients and tools.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pip install bec_launcher
9
+ ```
10
+
11
+ For development:
12
+
13
+ ```bash
14
+ pip install -e ".[dev]"
15
+ ```
File without changes
@@ -0,0 +1,47 @@
1
+ """
2
+ Simple helpers for fetching available deployments.
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ import os
8
+ from typing import TypedDict
9
+
10
+
11
+ class DeploymentDict(TypedDict):
12
+ """
13
+ Dictionary structure for deployment names.
14
+ """
15
+
16
+ production: list[str]
17
+ test: list[str]
18
+
19
+
20
+ def get_available_deployments(base_path: str) -> DeploymentDict:
21
+ """
22
+ Get a list of available deployments by listing directories in the given base path.
23
+
24
+ Returns:
25
+ DeploymentDict: A dictionary with 'production' and 'test' keys containing lists of deployment names.
26
+ """
27
+ out: DeploymentDict = {"production": [], "test": []}
28
+
29
+ if not os.path.exists(base_path):
30
+ return out
31
+
32
+ for item in os.listdir(base_path):
33
+ # Skip if not a directory
34
+ if not os.path.isdir(os.path.join(base_path, item)):
35
+ continue
36
+
37
+ # Skip if ends with "deployments" or starts with "old"
38
+ if item.endswith("deployments") or item.startswith("old"):
39
+ continue
40
+
41
+ # If the item starts with "test_", add to test deployments
42
+ if item.startswith("test"):
43
+ out["test"].append(item)
44
+ else:
45
+ out["production"].append(item)
46
+
47
+ return out
@@ -0,0 +1,22 @@
1
+ from bec_launcher.deployments import get_available_deployments
2
+
3
+
4
+ def launch(base_path: str) -> None:
5
+ deployments = get_available_deployments(base_path)
6
+ print("Launching BEC Launcher...")
7
+
8
+
9
+ if __name__ == "__main__":
10
+ import argparse
11
+
12
+ parser = argparse.ArgumentParser(description="BEC Launcher")
13
+ parser.add_argument(
14
+ "--base-path",
15
+ type=str,
16
+ help="Base path for deployments, typically /sls/<beamline>/config/bec",
17
+ required=True,
18
+ )
19
+
20
+ args = parser.parse_args()
21
+ base_path = args.base_path
22
+ launch(base_path)
@@ -0,0 +1,105 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "bec_launcher"
7
+ version = "0.1.0"
8
+ description = "BEC Launcher: A launcher application for BEC clients and tools."
9
+ requires-python = ">=3.11"
10
+ classifiers = [
11
+ "Development Status :: 3 - Alpha",
12
+ "Programming Language :: Python :: 3",
13
+ "Topic :: Scientific/Engineering",
14
+ ]
15
+
16
+ dependencies = []
17
+
18
+ [project.optional-dependencies]
19
+ dev = [
20
+ "black~=25.0",
21
+ "isort~=5.13, >=5.13.2",
22
+ "coverage~=7.0",
23
+ "pylint~=3.0",
24
+ "pytest-random-order~=1.1",
25
+ "pytest ~= 8.0",
26
+ ]
27
+
28
+ [project.urls]
29
+ "Bug Tracker" = "https://github.com/bec-project/bec_launcher/issues"
30
+ Homepage = "https://github.com/bec-project/bec_launcher"
31
+ documentation = "https://bec.readthedocs.org"
32
+ changelog = "https://github.com/bec-project/bec_launcher/blob/main/CHANGELOG.md"
33
+
34
+ [tool.hatch.build.targets.wheel]
35
+ include = ["*"]
36
+
37
+ [tool.isort]
38
+ profile = "black"
39
+ line_length = 100
40
+ multi_line_output = 3
41
+ include_trailing_comma = true
42
+
43
+ [tool.black]
44
+ line-length = 100
45
+ skip-magic-trailing-comma = true
46
+
47
+ [tool.pylint.basic]
48
+ # Good variable names regexes, separated by a comma. If names match any regex,
49
+ # they will always be accepted
50
+ good-names-rgxs = [
51
+ ".*scanID.*",
52
+ ".*RID.*",
53
+ ".*pointID.*",
54
+ ".*ID.*",
55
+ ".*_2D.*",
56
+ ".*_1D.*",
57
+ ]
58
+
59
+ [tool.semantic_release]
60
+ build_command = "python -m build"
61
+ version_toml = ["pyproject.toml:project.version"]
62
+
63
+ [tool.semantic_release.commit_author]
64
+ env = "GIT_COMMIT_AUTHOR"
65
+ default = "semantic-release <semantic-release>"
66
+
67
+ [tool.semantic_release.commit_parser_options]
68
+ allowed_tags = [
69
+ "build",
70
+ "chore",
71
+ "ci",
72
+ "docs",
73
+ "feat",
74
+ "fix",
75
+ "perf",
76
+ "style",
77
+ "refactor",
78
+ "test",
79
+ ]
80
+ minor_tags = ["feat"]
81
+ patch_tags = ["fix", "perf"]
82
+ default_bump_level = 0
83
+
84
+ [tool.semantic_release.remote]
85
+ name = "origin"
86
+ type = "github"
87
+ ignore_token_for_push = true
88
+
89
+ [tool.semantic_release.remote.token]
90
+ env = "GH_TOKEN"
91
+
92
+ [tool.semantic_release.publish]
93
+ dist_glob_patterns = ["dist/*"]
94
+ upload_to_vcs_release = true
95
+
96
+ [tool.coverage.report]
97
+ skip_empty = true # exclude empty *files*, e.g. __init__.py, from the report
98
+ exclude_lines = [
99
+ "pragma: no cover",
100
+ "if TYPE_CHECKING:",
101
+ "return NotImplemented",
102
+ "raise NotImplementedError",
103
+ "\\.\\.\\.",
104
+ 'if __name__ == "__main__":',
105
+ ]
@@ -0,0 +1,161 @@
1
+ """
2
+ Tests for deployments module.
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ from pathlib import Path
8
+
9
+ import pytest
10
+
11
+ from bec_launcher.deployments import get_available_deployments
12
+
13
+
14
+ @pytest.fixture
15
+ def temp_deployment_dir(tmpdir):
16
+ """Create a temporary directory structure for testing."""
17
+ base_path = Path(tmpdir)
18
+
19
+ # Create various directories
20
+ (base_path / "production").mkdir()
21
+ (base_path / "test").mkdir()
22
+ (base_path / "old_production_deployments").mkdir()
23
+ (base_path / "old_test_deployments").mkdir()
24
+ (base_path / "production_deployments").mkdir()
25
+ (base_path / "test_deployments").mkdir()
26
+
27
+ # Create a file (should be ignored)
28
+ (base_path / "readme.txt").touch()
29
+
30
+ return str(base_path)
31
+
32
+
33
+ def test_get_available_deployments_filters_correctly(temp_deployment_dir):
34
+ """Test that only valid deployment names are returned."""
35
+ result = get_available_deployments(temp_deployment_dir)
36
+
37
+ assert "production" in result["production"]
38
+ assert "test" in result["test"]
39
+ assert len(result["production"]) == 1
40
+ assert len(result["test"]) == 1
41
+
42
+
43
+ def test_get_available_deployments_excludes_old_directories(temp_deployment_dir):
44
+ """Test that directories starting with 'old' are excluded."""
45
+ result = get_available_deployments(temp_deployment_dir)
46
+
47
+ all_deployments = result["production"] + result["test"]
48
+ assert not any(d.startswith("old") for d in all_deployments)
49
+
50
+
51
+ def test_get_available_deployments_excludes_deployment_suffixed_directories(temp_deployment_dir):
52
+ """Test that directories ending with 'deployments' are excluded."""
53
+ result = get_available_deployments(temp_deployment_dir)
54
+
55
+ all_deployments = result["production"] + result["test"]
56
+ assert not any(d.endswith("deployments") for d in all_deployments)
57
+
58
+
59
+ def test_get_available_deployments_excludes_files(temp_deployment_dir):
60
+ """Test that files are not included in the results."""
61
+ result = get_available_deployments(temp_deployment_dir)
62
+
63
+ all_deployments = result["production"] + result["test"]
64
+ assert "readme.txt" not in all_deployments
65
+
66
+
67
+ def test_get_available_deployments_nonexistent_path():
68
+ """Test behavior when the base path doesn't exist."""
69
+ result = get_available_deployments("/nonexistent/path")
70
+
71
+ assert result == {"production": [], "test": []}
72
+
73
+
74
+ def test_get_available_deployments_empty_directory(tmpdir):
75
+ """Test behavior with an empty directory."""
76
+ result = get_available_deployments(str(tmpdir))
77
+
78
+ assert result == {"production": [], "test": []}
79
+
80
+
81
+ def test_get_available_deployments_separates_test_and_production(tmpdir):
82
+ """Test that test deployments are correctly separated from production."""
83
+ base_path = Path(tmpdir)
84
+
85
+ # Create test deployments
86
+ (base_path / "test").mkdir()
87
+ (base_path / "test_env1").mkdir()
88
+ (base_path / "test_env2").mkdir()
89
+
90
+ # Create production deployments
91
+ (base_path / "production").mkdir()
92
+ (base_path / "staging").mkdir()
93
+ (base_path / "dev").mkdir()
94
+
95
+ result = get_available_deployments(str(base_path))
96
+
97
+ assert "test" in result["test"]
98
+ assert "test_env1" in result["test"]
99
+ assert "test_env2" in result["test"]
100
+ assert len(result["test"]) == 3
101
+
102
+ assert "production" in result["production"]
103
+ assert "staging" in result["production"]
104
+ assert "dev" in result["production"]
105
+
106
+
107
+ def test_get_available_deployments_complex_scenario(tmpdir):
108
+ """Test with a complex directory structure."""
109
+ base_path = Path(tmpdir)
110
+
111
+ # Valid deployments
112
+ (base_path / "production").mkdir()
113
+ (base_path / "test").mkdir()
114
+ (base_path / "staging").mkdir()
115
+ (base_path / "test_feature").mkdir()
116
+
117
+ # Should be excluded
118
+ (base_path / "old_production").mkdir()
119
+ (base_path / "old_test").mkdir()
120
+ (base_path / "production_deployments").mkdir()
121
+ (base_path / "test_deployments").mkdir()
122
+ (base_path / "old_deployments").mkdir()
123
+
124
+ # Files (should be ignored)
125
+ (base_path / "config.yaml").touch()
126
+
127
+ result = get_available_deployments(str(base_path))
128
+
129
+ # Check production deployments
130
+ assert "production" in result["production"]
131
+ assert "staging" in result["production"]
132
+ assert len(result["production"]) == 2
133
+
134
+ # Check test deployments
135
+ assert "test" in result["test"]
136
+ assert "test_feature" in result["test"]
137
+ assert len(result["test"]) == 2
138
+
139
+ # Ensure excluded items are not present
140
+ all_deployments = result["production"] + result["test"]
141
+ assert "old_production" not in all_deployments
142
+ assert "old_test" not in all_deployments
143
+ assert "production_deployments" not in all_deployments
144
+ assert "test_deployments" not in all_deployments
145
+ assert "old_deployments" not in all_deployments
146
+
147
+
148
+ def test_get_available_deployments_custom_names(tmpdir):
149
+ """Test with custom deployment names."""
150
+ base_path = Path(tmpdir)
151
+
152
+ # Create custom named deployments
153
+ (base_path / "saxs").mkdir()
154
+ (base_path / "test_saxs").mkdir()
155
+
156
+ result = get_available_deployments(str(base_path))
157
+
158
+ assert "saxs" in result["production"]
159
+ assert len(result["production"]) == 1
160
+ assert "test_saxs" in result["test"]
161
+ assert len(result["test"]) == 1