Skip to content

Commit d17fc21

Browse files
authored
Kick off (#1)
This is the first version ready for reviews.
1 parent dd80b9d commit d17fc21

File tree

201 files changed

+200791
-3
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

201 files changed

+200791
-3
lines changed

.github/workflows/ci.yml

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [ master, main ]
6+
tags: [ "**" ]
7+
pull_request:
8+
branches: [ "**" ]
9+
10+
jobs:
11+
Check:
12+
runs-on: ubuntu-latest
13+
strategy:
14+
matrix:
15+
python-version: ['3.10', '3.11', '3.12']
16+
17+
steps:
18+
- uses: actions/checkout@master
19+
20+
- name: Set up Python ${{ matrix.python-version }}
21+
uses: actions/setup-python@v2
22+
with:
23+
python-version: ${{ matrix.python-version }}
24+
25+
- name: Install dependencies
26+
run: |
27+
python3 -m pip install --upgrade pip
28+
pip3 install --upgrade coveralls
29+
pip3 install -e .
30+
pip3 install -e dev/
31+
32+
- name: Run precommit
33+
run: |
34+
python3 dev/continuous_integration/precommit.py
35+
36+
- name: Upload Coverage
37+
run: coveralls --service=github
38+
env:
39+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
40+
COVERALLS_FLAG_NAME: ${{ matrix.python-version }}
41+
COVERALLS_PARALLEL: true
42+
43+
Finish-Coveralls:
44+
name: Finish Coveralls
45+
needs: [Check]
46+
runs-on: ubuntu-latest
47+
container: python:3-slim
48+
steps:
49+
- name: Finish Coveralls
50+
run: |
51+
pip3 install --upgrade coveralls
52+
coveralls --finish --service=github
53+
env:
54+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Based on https://github.com/actions/starter-workflows/blob/main/ci/python-publish.yml
2+
name: Publish to Pypi
3+
4+
on:
5+
release:
6+
types: [created]
7+
8+
push:
9+
branches:
10+
- '*/fixed-publishing-to-pypi'
11+
12+
jobs:
13+
deploy:
14+
15+
runs-on: ubuntu-latest
16+
17+
steps:
18+
- uses: actions/checkout@v2
19+
20+
- name: Set up Python
21+
uses: actions/setup-python@v2
22+
with:
23+
python-version: '3.x'
24+
25+
- name: Install dependencies
26+
run: |
27+
python -m pip install --upgrade pip
28+
pip install build setuptools wheel twine
29+
30+
- name: Build and publish
31+
env:
32+
TWINE_USERNAME: "__token__"
33+
TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}
34+
run: |
35+
python -m build --sdist --wheel
36+
twine upload dist/*

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
.idea/
2+
howto*.pdf
3+
deleteme*
4+
15
# Byte-compiled / optimized / DLL files
26
__pycache__/
37
*.py[cod]

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Marko Ristin (marko@ristin.ch, marko.ristin@gmail.com, rist@zhaw.ch) for Zurich University of Applied Sciences (ZHAW)

CONTRIBUTING.rst

Lines changed: 289 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,289 @@
1+
************
2+
Contributing
3+
************
4+
5+
Coordinate First
6+
================
7+
8+
Before you create a pull request, please `create a new issue`_ first to coordinate.
9+
10+
It might be that we are already working on the same or similar feature, but we haven't made our work visible yet.
11+
12+
.. _create a new issue: https://github.com/aas-core-works/aas-smt-codegen/issues/new
13+
14+
Create a Development Environment
15+
================================
16+
17+
We usually develop in a `virtual environment`_.
18+
To create one, change to the root directory of the repository and invoke:
19+
20+
.. code-block::
21+
22+
python -m venv venv
23+
24+
25+
You need to activate it. On *nix (Linux, Mac, *etc.*):
26+
27+
.. code-block::
28+
29+
source venv/bin/activate
30+
31+
and on Windows:
32+
33+
.. code-block::
34+
35+
venv\Scripts\activate
36+
37+
.. _virtual environment: https://docs.python.org/3/tutorial/venv.html
38+
39+
Install Development Dependencies
40+
================================
41+
42+
Once you activated the virtual environment, you can install the development dependencies using ``pip``:
43+
44+
.. code-block::
45+
46+
pip3 install --editable ./
47+
pip3 install --editable dev/
48+
49+
The `--editable <pip-editable_>`_ option is necessary so that all the changes made to the repository are automatically reflected in the virtual environment (see also `this StackOverflow question <pip-editable-stackoverflow_>`_).
50+
51+
.. _pip-editable: https://pip.pypa.io/en/stable/reference/pip_install/#install-editable
52+
.. _pip-editable-stackoverflow: https://stackoverflow.com/questions/35064426/when-would-the-e-editable-option-be-useful-with-pip-install
53+
54+
Background Literature
55+
=====================
56+
Please make yourself familiar with a general literature on compiler design.
57+
58+
For example, `Crafting Interpreters`_ is a good book.
59+
60+
.. _Crafting Interpreters: https://craftinginterpreters.com/
61+
62+
Coding Style Guide
63+
==================
64+
Typing
65+
------
66+
Always write explicit types in function arguments.
67+
If you really expect any type, mark that explicitly with ``Any``.
68+
Also always mark your local variables with a type if it can not be deduced.
69+
70+
For example:
71+
72+
.. code-block:: python
73+
74+
lst = [] # type: List[str]
75+
76+
For files, use ``typing.IO``.
77+
78+
We prefer to put types in comments if they are short for readability.
79+
However, put them in code when they are multi-line:
80+
81+
.. code-block:: python
82+
83+
some_map: Optional[
84+
Dict[
85+
SomeType,
86+
AnotherType
87+
]
88+
] = None
89+
90+
Variable Names
91+
--------------
92+
Put ``_set`` for sets.
93+
94+
Prefer to designate the key with ``_by_`` suffix.
95+
For example, ``our_types_by_name`` is a mapping string (a name) 🠒 ``OurType``.
96+
97+
Method Names
98+
------------
99+
Do not put ``get_`` in method names.
100+
If you want to make sure that the reader understands that some method is going to take longer than just a simple getter, prefix it with a meaningful verb such as ``compute_...``, ``collect_...`` or ``retrieve_...``.
101+
102+
Property Names
103+
--------------
104+
Do not duplicate module (package) or class names in the property names.
105+
106+
For example, if you have a class called ``Features``, and want to add property to hold feature names, call the property simply ``names`` and not ``feature_names``.
107+
The caller code would otherwise redundantly read ``Features.feature_names`` or ``features.feature_names``.
108+
109+
Module Names
110+
------------
111+
Do not call your modules, classes or functions ``..._helpers`` or ``..._utils``.
112+
A general name is most probably an indicator that there is either a flaw in the design (*e.g.*, tight coupling which should be decoupled) or that there needs to be more thought spent on the naming.
113+
114+
If you have shared functionality in a module used by all or most of the submodules, put it in ``common`` submodule.
115+
116+
Programming Paradigm
117+
--------------------
118+
* Prefer functional programming to object-oriented programming.
119+
* Better be explicit about the data flow than implicit.
120+
* Prefer namespaced functions in a (sub)module instead of class methods.
121+
* Side effects are difficult to trace.
122+
* Context of a function is immediately visible when you look at arguments.
123+
A function is much easier to isolate and unit test than a class method.
124+
* Use inheritance only when you need polymorphism.
125+
* Do not use inheritance to share implementation; use namespaced functions for that.
126+
* Prefer simplicity with a small number of classes; see http://thedailywtf.com/articles/Enterprise-Dependency-The-Next-Generation
127+
* Use stateful objects in moderation.
128+
* Some thoughts: https://medium.com/@cscalfani/goodbye-object-oriented-programming-a59cda4c0e53
129+
130+
Anti-patterns from Clean Code
131+
-----------------------------
132+
Do not split script-like parts of the code into small chunks of one-time usage functions.
133+
134+
Use comments or regions to give overview.
135+
136+
It's ok to have long scripts that are usually more readable than a patchwork of small functions.
137+
Jumping around a file while keeping the context in head is difficult and error-prone.
138+
139+
See also this discussion for more rationale: https://github.com/johnousterhout/aposd-vs-clean-code
140+
141+
No Stateful Singletons
142+
----------------------
143+
Do not *ever* use stateful singletons.
144+
Pass objects down the calling stack even if it seems tedious at first.
145+
146+
See: https://kentonshouse.com/singletons
147+
148+
Imports
149+
-------
150+
Very common symbols such as ``Identifier`` can be imported without prefix.
151+
Usually, these symbols reside in ``aas_smt_codegen.common``.
152+
153+
In addition, do not prefix ``typing`` symbols such as ``List`` or ``Mapping``, and the assertion functions from `icontract`_ design-by-contract library (see below).
154+
Otherwise, the code would be completely unreadable.
155+
156+
All other symbols should be imported with an aliased prefix corresponding to the module.
157+
For example:
158+
159+
.. code-block::python
160+
161+
from aas_smt_codegen.opcua import (
162+
naming as opcua_naming
163+
)
164+
165+
Filesystem
166+
----------
167+
Use ``pathlib``, not ``os.path``.
168+
169+
Design-by-contract
170+
------------------
171+
Use `design-by-contract`_ as much as possible.
172+
We use `icontract`_ library.
173+
174+
.. _design-by-contract: https://en.wikipedia.org/wiki/Design_by_contract
175+
.. _icontract: https://icontract.readthedocs.io/
176+
177+
``Final`` and Constant Containers
178+
---------------------------------
179+
Prefer immutable to mutable objects and structures.
180+
181+
Distinguish between internally and externally mutable structures.
182+
Annotate for immutability if the structures are only internally mutable.
183+
184+
Avoid Double-Asterisk (``**``) Operator
185+
---------------------------------------
186+
Double-asterisks are unpredictable for the reader, as all the keys need to be kept in mind, and overridden keys are simply ignored.
187+
188+
Please do not use ``**`` operator unless it is utterly necessary, and explain in the comment why it is necessary.
189+
Check for overwriting keys where appropriate.
190+
191+
Classes over ``TypedDict``
192+
---------------------------
193+
Always use classes in the code.
194+
195+
Use ``TypedDict`` only if you have to deal with serialization (*e.g.*, to JSON).
196+
197+
Code Regions
198+
------------
199+
We intensively use PyCharms ``# region ...`` and ``# endregion`` to structure code into regions.
200+
201+
Comments
202+
--------
203+
Mark notes with ``# NOTE ({github username}):``.
204+
205+
No ``# TODO`` in the code, please.
206+
207+
Comment only where the comments really add information.
208+
Do not write self-evident comments.
209+
210+
Comments should be in proper English.
211+
Write in simple present tense; avoid imperative mood.
212+
213+
Be careful about the capitals.
214+
Start the sentence with a capital.
215+
If you list bullet points, start with a capital, and do not forget conjectures:
216+
217+
.. code-block:: python
218+
219+
# * We ...,
220+
# * Then, ..., and finally
221+
# * We ...
222+
223+
The abbreviations are to be written properly in capitals (*e.g.*, ``JSON`` and not ``json``).
224+
225+
No code is allowed in the comments since it always rots.
226+
227+
Docstrings
228+
----------
229+
You can write full-blown Sphinx docstrings, if you wish.
230+
231+
In many cases, a short docstring is enough.
232+
We are not religious about ``:param ...:`` and ``:return`` fields.
233+
234+
Follow `PEP 287`_.
235+
Use imperative mood in the docstrings.
236+
237+
.. _PEP 287: https://peps.python.org/pep-0287/
238+
239+
Testing
240+
-------
241+
Write unit tests for everything that can be obviously tested at the function/class level.
242+
243+
For many inter-dependent code regions, writing unit tests is too tedious or nigh impossible to later maintain.
244+
For such parts of the system, prefer integration tests with comparisons against initially recorded and reviewed golden data.
245+
See, for example, ``tests/opcua/test_main.py`` or ``tests/test_frontend.py``.
246+
247+
The golden test data resides in ``test_data/``.
248+
The structure of the test data directory follows in general the test module structure.
249+
250+
Pre-commit Checks
251+
=================
252+
253+
We provide a battery of pre-commit checks to make the code uniform and consistent across the code base.
254+
255+
We use `black`_ to format the code and use the default maximum line length of 88 characters.
256+
257+
.. _black: https://pypi.org/project/black/
258+
259+
To run all pre-commit checks, run from the root directory:
260+
261+
.. code-block::
262+
263+
python continuous_integration/precommit.py
264+
265+
You can automatically re-format the code and fix certain files automatically with:
266+
267+
.. code-block::
268+
269+
python continuous_integration/precommit.py --overwrite
270+
271+
The pre-commit script also runs as part of our continuous integration pipeline.
272+
273+
Write Commit Message
274+
====================
275+
276+
We follow Chris Beams' `guidelines on commit messages`_:
277+
278+
1) Separate subject from body with a blank line
279+
2) Limit the subject line to 50 characters
280+
3) Capitalize the subject line
281+
4) Do not end the subject line with a period
282+
5) Use the imperative mood in the subject line, full sentences in the body
283+
6) Wrap the body at 72 characters
284+
7) Use the body to explain *what* and *why* vs. *how*
285+
286+
.. _guidelines on commit messages: https://chris.beams.io/posts/git-commit/
287+
288+
If you are merging in a pull request, please squash before merging.
289+
We want to keep the Git history as simple as possible, and the commits during the development are rarely insightful later.

0 commit comments

Comments
 (0)