You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Update CONTRIBUTING.md and README.md for clarity and consistency
- Standardized formatting and capitalization in CONTRIBUTING.md for improved readability.
- Enhanced instructions in README.md, including clearer setup and running commands, and added details about importing time tracking data.
- Updated version number in uv.lock to 2.0.0a1.
3. Install your local copy into a virtualenv. Assuming you have
65
-
virtualenvwrapper installed, this is how you set up your fork for
66
-
local development:
64
+
3. Install dependencies with [uv](https://docs.astral.sh/uv/):
67
65
68
-
``` shell
69
-
$ mkvirtualenv tuttle
70
-
$ cd tuttle/
71
-
$ python setup.py develop
66
+
```shell
67
+
cd tuttle/
68
+
uv sync
72
69
```
73
70
74
71
4. Create a branch forlocal development:
75
72
76
-
```shell
77
-
$ git checkout -b name-of-your-bugfix-or-feature
73
+
```shell
74
+
git checkout -b name-of-your-bugfix-or-feature
78
75
```
79
76
80
77
Now you can make your changes locally.
81
78
82
79
83
80
**Install the pre-commit hooks before making your first commit to ensure that you match the code style**:
84
81
85
-
```shell
86
-
$ pre-commit install
82
+
```shell
83
+
pre-commit install
87
84
```
85
+
88
86
5. If you haven't done so already, install and/or activate
89
87
[pyright](https://github.com/microsoft/pyright).
90
88
The "basic" level should suffice and help you to avoid type errors.
@@ -98,20 +96,20 @@ local development.
98
96
Oftentimes, type errors indicate bad design,
99
97
so keep refactoring in mind as a third option.
100
98
101
-
6. When you\'re done making changes, check that your changes pass
102
-
code style checks and the tests:
99
+
6. When you're done making changes, check that your changes pass
100
+
the tests:
103
101
104
-
```shell
105
-
$ pytest
102
+
```shell
103
+
uv run pytest
106
104
```
107
105
108
106
109
107
7. Commit your changes and push your branch to GitHub:
110
108
111
-
```shell
112
-
$ git add .
113
-
$ git commit -m "Your detailed description of your changes."
114
-
$ git push origin name-of-your-bugfix-or-feature
109
+
```shell
110
+
git add .
111
+
git commit -m "Your detailed description of your changes."
112
+
git push origin name-of-your-bugfix-or-feature
115
113
```
116
114
117
115
8. Submit a pull request through the GitHub website.
@@ -122,46 +120,48 @@ Before you submit a pull request, check that it meets these guidelines:
122
120
123
121
1. The pull request should include tests.
124
122
2. If the pull request adds functionality, the docs should be updated.
125
-
Put your new functionality into a functionwith a docstring, and add
126
-
the feature to the list in README.rst.
127
-
3. The pull request should work for Python 3.8, 3.9, 3.10.
123
+
Put your new functionality into a function with a docstring.
124
+
3. The pull request should work for Python 3.10, 3.11, 3.12, and 3.13.
128
125
129
126
# Tips
130
127
131
128
To run a subset of tests:
132
129
133
-
``` shell
134
-
$ pytest tests.test_tuttle
130
+
```shell
131
+
uv run pytest tuttle_tests/test_model.py
132
+
```
133
+
134
+
To run a specific test:
135
+
136
+
```shell
137
+
uv run pytest tuttle_tests/test_model.py::TestContract::test_valid_instantiation
135
138
```
136
139
137
140
# Deploying
138
141
139
-
A reminder for the maintainers on how to deploy. Make sure all your
140
-
changes are committed (including an entry in HISTORY.rst). Then run:
142
+
Make sure all your changes are committed. Then run:
141
143
142
-
```shell
143
-
$ bump2version patch # possible: major / minor / patch
144
-
$ git push
145
-
$ git push --tags
144
+
```shell
145
+
bump2version patch # possible: major / minor / patch
146
+
git push
147
+
git push --tags
146
148
```
147
149
148
-
Travis will then deploy to PyPI if tests pass.
149
-
150
150
151
151
## Architecture Notes
152
152
153
153
**The View**
154
154
155
-
- builds Ui,
156
-
- reacts to data changes (by updating the Ui)
155
+
- builds UI,
156
+
- reacts to data changes (by updating the UI)
157
157
- listens for events and forwards them to the Intent
158
158
159
159
**The Intent**
160
160
161
161
- receives events
162
162
- if some data is affected by the event, figure out which data source corresponds to that data
163
163
- transforms the event data to the data format required by the data source
164
-
- transform returned data source data to the data format required by the Ui
164
+
- transform returned data source data to the data format required by the UI
165
165
- else, no data is affected by the event, handle the event (often using a util class).
166
166
- an example of this is sending invoices by mail.
167
167
@@ -174,12 +174,12 @@ Travis will then deploy to PyPI if tests pass.
174
174
- defines classes that manipulate this source (open, read, write, ....)
175
175
176
176
177
-
As you go outer in layers (the outmost layer is the Ui, the innermost is the data layer), communication can occur down_ward across layers, and horizontally (for lack of a better word) BUT a layer cannot skip the layer directly below it. This is to say:
177
+
As you go outer in layers (the outmost layer is the UI, the innermost is the data layer), communication can occur downward across layers, and horizontally, BUT a layer cannot skip the layer directly below it. This is to say:
178
178
179
-
* Data sources can communicate with each other. Thus `ClientDatasource.delete_client` can call. `ContractDatasource.get_contract` for example.
179
+
* Data sources can communicate with each other. Thus `ClientDatasource.delete_client` can call `ContractDatasource.get_contract`for example.
180
180
181
-
* Intents can communicate with each other, and with any data source. Thus `ClientIntent` can call `ContractIntent` or `ContractDatasource` for example.
182
-
The Ui can communicate with any intent (though often the Ui is tied to only a single intent, and the intent can instead call the 'other' intent). But it cannot communicate with a data source -> this would violate the donotskiplayers rule.
183
-
An inner layer cannot have a dependency on the layer above it. Thus an intent cannot instantiate a Ui class, and a data source cannot instantiate an Intent class.
181
+
* Intents can communicate with each other, and with any data source. Thus `ClientIntent` can call `ContractIntent` or `ContractDatasource`for example.
182
+
The UI can communicate with any intent (though often the UI is tied to only a single intent, and the intent can instead call the "other" intent). But it cannot communicate with a data source -- this would violate the do-not-skip-layers rule.
183
+
An inner layer cannot have a dependency on the layer above it. Thus an intent cannot instantiate a UI class, and a data source cannot instantiate an Intent class.
Track the time you spend on your projects. Import from your cloud calendar or from your favorite time tracking tool.
49
+
Track the time you spend on your projects. Import from your cloud calendar (iCloud), from an ICS file, or from a CSV export of your favorite time tracking tool.
Generate invoices and timesheets automatically from your time tracking data. Export to PDF and send via email.
56
+
Generate invoices and timesheets automatically from your time tracking data, or create invoices manually by entering the quantity of hours or days directly. Export to PDF and send via email.
0 commit comments