evernote2unbent 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.
- evernote2unbent-0.1.0/.github/workflows/publish.yml +61 -0
- evernote2unbent-0.1.0/.github/workflows/test.yml +26 -0
- evernote2unbent-0.1.0/.gitignore +10 -0
- evernote2unbent-0.1.0/LICENSE +21 -0
- evernote2unbent-0.1.0/PKG-INFO +144 -0
- evernote2unbent-0.1.0/README.md +121 -0
- evernote2unbent-0.1.0/pyproject.toml +56 -0
- evernote2unbent-0.1.0/src/evernote2unbent/__init__.py +3 -0
- evernote2unbent-0.1.0/src/evernote2unbent/cli.py +348 -0
- evernote2unbent-0.1.0/src/evernote2unbent/client.py +188 -0
- evernote2unbent-0.1.0/src/evernote2unbent/config.py +77 -0
- evernote2unbent-0.1.0/src/evernote2unbent/errors.py +6 -0
- evernote2unbent-0.1.0/src/evernote2unbent/token_store.py +67 -0
- evernote2unbent-0.1.0/src/evernote2unbent/uploader.py +218 -0
- evernote2unbent-0.1.0/tests/test_config.py +99 -0
- evernote2unbent-0.1.0/tests/test_uploader.py +349 -0
- evernote2unbent-0.1.0/uv.lock +709 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
name: Publish
|
|
2
|
+
|
|
3
|
+
# Publishing is driven by tags, so a release is `git tag v0.1.0 && git push --tags`
|
|
4
|
+
# rather than a checklist someone has to remember at the end of a long day.
|
|
5
|
+
on:
|
|
6
|
+
push:
|
|
7
|
+
tags: ["v*"]
|
|
8
|
+
# Manual runs go to TestPyPI, so the publishing path itself can be exercised without
|
|
9
|
+
# burning a real version number — PyPI refuses to reuse one, even after a delete.
|
|
10
|
+
workflow_dispatch:
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
test:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
strategy:
|
|
16
|
+
matrix:
|
|
17
|
+
python-version: ["3.10", "3.13"]
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v4
|
|
20
|
+
- uses: astral-sh/setup-uv@v5
|
|
21
|
+
with:
|
|
22
|
+
enable-cache: true
|
|
23
|
+
- run: uv python install ${{ matrix.python-version }}
|
|
24
|
+
- run: uv sync --group test --group dev
|
|
25
|
+
- run: uv run ruff check src tests
|
|
26
|
+
- run: uv run ruff format --check src tests
|
|
27
|
+
- run: uv run pytest tests/ -q
|
|
28
|
+
|
|
29
|
+
publish:
|
|
30
|
+
# Gated on the tests: a tag that fails them should not become a release anyone can
|
|
31
|
+
# install, and PyPI versions cannot be replaced once published.
|
|
32
|
+
needs: test
|
|
33
|
+
runs-on: ubuntu-latest
|
|
34
|
+
environment: release
|
|
35
|
+
permissions:
|
|
36
|
+
# Trusted Publishing: PyPI verifies this workflow's identity through OIDC, so there
|
|
37
|
+
# is no API token to store, rotate, or leak.
|
|
38
|
+
id-token: write
|
|
39
|
+
steps:
|
|
40
|
+
- uses: actions/checkout@v4
|
|
41
|
+
- uses: astral-sh/setup-uv@v5
|
|
42
|
+
- run: uv build
|
|
43
|
+
|
|
44
|
+
- name: Check the tag matches the version in pyproject.toml
|
|
45
|
+
if: startsWith(github.ref, 'refs/tags/')
|
|
46
|
+
run: |
|
|
47
|
+
TAG="${GITHUB_REF#refs/tags/v}"
|
|
48
|
+
VERSION=$(uv run python -c "import tomllib,pathlib;print(tomllib.loads(pathlib.Path('pyproject.toml').read_text())['project']['version'])")
|
|
49
|
+
if [ "$TAG" != "$VERSION" ]; then
|
|
50
|
+
echo "Tag v$TAG does not match pyproject version $VERSION." >&2
|
|
51
|
+
echo "Bump the version, commit, then tag." >&2
|
|
52
|
+
exit 1
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
- name: Publish to TestPyPI
|
|
56
|
+
if: github.event_name == 'workflow_dispatch'
|
|
57
|
+
run: uv publish --publish-url https://test.pypi.org/legacy/
|
|
58
|
+
|
|
59
|
+
- name: Publish to PyPI
|
|
60
|
+
if: startsWith(github.ref, 'refs/tags/')
|
|
61
|
+
run: uv publish
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
name: Test
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
test:
|
|
10
|
+
runs-on: ${{ matrix.os }}
|
|
11
|
+
strategy:
|
|
12
|
+
fail-fast: false
|
|
13
|
+
matrix:
|
|
14
|
+
# The three platforms people migrate on. Windows is included because the token
|
|
15
|
+
# and config stores touch file modes, which behave differently there.
|
|
16
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
17
|
+
python-version: ["3.10", "3.13"]
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v4
|
|
20
|
+
- uses: astral-sh/setup-uv@v5
|
|
21
|
+
with:
|
|
22
|
+
enable-cache: true
|
|
23
|
+
- run: uv python install ${{ matrix.python-version }}
|
|
24
|
+
- run: uv sync --group test --group dev
|
|
25
|
+
- run: uv run ruff check src tests
|
|
26
|
+
- run: uv run pytest tests/ -q
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 C Deutsch
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: evernote2unbent
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Move your Evernote notes into Unbent, without an ENEX file in between.
|
|
5
|
+
Project-URL: Homepage, https://github.com/cdeutsch/evernote2unbent
|
|
6
|
+
Project-URL: Unbent, https://unbent.app
|
|
7
|
+
Project-URL: evernote-backup, https://github.com/vzhd1701/evernote-backup
|
|
8
|
+
Author: C Deutsch
|
|
9
|
+
License: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: enex,evernote,export,migration,notes,unbent
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Topic :: Utilities
|
|
18
|
+
Requires-Python: >=3.10
|
|
19
|
+
Requires-Dist: click>=8.1
|
|
20
|
+
Requires-Dist: evernote-backup>=1.14.0
|
|
21
|
+
Requires-Dist: requests>=2.31
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
|
|
24
|
+
# evernote2unbent
|
|
25
|
+
|
|
26
|
+
Move your Evernote notes into [Unbent](https://unbent.app) — notes, notebooks, tags and
|
|
27
|
+
attachments — without exporting an ENEX file first.
|
|
28
|
+
|
|
29
|
+
Evernote has no export API, so every other route runs through the desktop client's
|
|
30
|
+
File → Export, which is manual, unreliable past a few thousand notes, and produces
|
|
31
|
+
multi-gigabyte files you then have to feed somewhere. This syncs your account with
|
|
32
|
+
[evernote-backup](https://github.com/vzhd1701/evernote-backup) and uploads straight from
|
|
33
|
+
its local database.
|
|
34
|
+
|
|
35
|
+
## Install
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
uv tool install evernote2unbent
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Or with pipx:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
pipx install evernote2unbent
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Use
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
evernote2unbent migrate
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
That signs you in to Evernote, syncs your account to a local database, then uploads
|
|
54
|
+
everything to Unbent. It asks which Unbent instance to use the first time and remembers
|
|
55
|
+
the answer.
|
|
56
|
+
|
|
57
|
+
**Start with one notebook** to see the result before moving everything. The sync still
|
|
58
|
+
fetches your whole account — it is the upload that is scoped:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
evernote2unbent migrate -n "Some Notebook"
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Interrupted runs are safe to repeat: the sync is incremental, and notes that already
|
|
65
|
+
landed are skipped rather than duplicated.
|
|
66
|
+
|
|
67
|
+
### Doing the steps separately
|
|
68
|
+
|
|
69
|
+
`migrate` runs [evernote-backup](https://github.com/vzhd1701/evernote-backup) for you. If
|
|
70
|
+
you already use it, or want the ENEX files too, run the halves yourself:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
evernote-backup init-db
|
|
74
|
+
evernote-backup sync
|
|
75
|
+
evernote2unbent upload
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Re-running is safe
|
|
79
|
+
|
|
80
|
+
Unbent keys each note on a hash of its title and body, so a note that already landed is
|
|
81
|
+
skipped rather than duplicated. That makes an interrupted upload resumable by simply
|
|
82
|
+
repeating the command — and a note whose attachments failed partway gets only the missing
|
|
83
|
+
files on the next run.
|
|
84
|
+
|
|
85
|
+
Nothing here deletes or modifies anything in Evernote.
|
|
86
|
+
|
|
87
|
+
## Options
|
|
88
|
+
|
|
89
|
+
| Flag | Meaning |
|
|
90
|
+
| --- | --- |
|
|
91
|
+
| `-d, --database` | The database `evernote-backup sync` wrote (default `en_backup.db`) |
|
|
92
|
+
| `-n, --notebook` | Only this notebook. Repeatable |
|
|
93
|
+
| `-t, --tag` | Only notes with this tag. Repeatable |
|
|
94
|
+
| `--include-trash` | Include notes from Evernote's trash |
|
|
95
|
+
| `--url` | Instance for one command, without storing it |
|
|
96
|
+
|
|
97
|
+
## Signing in
|
|
98
|
+
|
|
99
|
+
`login` prints a short code and a link. Approving it in a browser you are already signed in
|
|
100
|
+
to grants an ordinary session — no password is typed into the terminal, and no long-lived
|
|
101
|
+
key is pasted from a settings page.
|
|
102
|
+
|
|
103
|
+
The token is stored in `~/.config/unbent/credentials.json` at mode `0600`, keyed by
|
|
104
|
+
instance so a token for one server is never sent to another. `logout` forgets it locally;
|
|
105
|
+
signing out everywhere in Unbent revokes it for real.
|
|
106
|
+
|
|
107
|
+
## Which instance
|
|
108
|
+
|
|
109
|
+
There is deliberately no default. A guessed instance means a forgotten flag can send a
|
|
110
|
+
migration to a server you did not choose, and that failure is silent, because uploading to
|
|
111
|
+
the wrong Unbent still succeeds.
|
|
112
|
+
|
|
113
|
+
The answer is stored in `~/.config/unbent/config.json` — plain JSON, mode `0644`, separate
|
|
114
|
+
from the credentials file so changing a URL never means opening one with a token in it.
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
evernote2unbent set-url https://unbent.app
|
|
118
|
+
evernote2unbent show-config
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
`$UNBENT_URL` overrides it for a shell session, `--url` for a single command.
|
|
122
|
+
|
|
123
|
+
## What gets converted
|
|
124
|
+
|
|
125
|
+
Notes arrive as Markdown. The conversion happens server-side in Unbent, which is why this
|
|
126
|
+
package does not implement one: Unbent's own importer already has a tested ENML converter,
|
|
127
|
+
and a second implementation here would drift from it.
|
|
128
|
+
|
|
129
|
+
Attachments upload separately as raw bytes and are linked from the note body by their
|
|
130
|
+
content hash, which is how an inline image ends up in the right place.
|
|
131
|
+
|
|
132
|
+
## Credit
|
|
133
|
+
|
|
134
|
+
The hard part — Evernote authentication, the Thrift API client, and incremental sync — is
|
|
135
|
+
[evernote-backup](https://github.com/vzhd1701/evernote-backup) by
|
|
136
|
+
[vzhd1701](https://github.com/vzhd1701), used here as a dependency rather than forked. This
|
|
137
|
+
package adds an uploader and a CLI on top of it and modifies none of it.
|
|
138
|
+
|
|
139
|
+
If you want ENEX files rather than a migration, use evernote-backup directly; it does that
|
|
140
|
+
well and this is not a replacement for it.
|
|
141
|
+
|
|
142
|
+
## License
|
|
143
|
+
|
|
144
|
+
MIT
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# evernote2unbent
|
|
2
|
+
|
|
3
|
+
Move your Evernote notes into [Unbent](https://unbent.app) — notes, notebooks, tags and
|
|
4
|
+
attachments — without exporting an ENEX file first.
|
|
5
|
+
|
|
6
|
+
Evernote has no export API, so every other route runs through the desktop client's
|
|
7
|
+
File → Export, which is manual, unreliable past a few thousand notes, and produces
|
|
8
|
+
multi-gigabyte files you then have to feed somewhere. This syncs your account with
|
|
9
|
+
[evernote-backup](https://github.com/vzhd1701/evernote-backup) and uploads straight from
|
|
10
|
+
its local database.
|
|
11
|
+
|
|
12
|
+
## Install
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
uv tool install evernote2unbent
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Or with pipx:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pipx install evernote2unbent
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Use
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
evernote2unbent migrate
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
That signs you in to Evernote, syncs your account to a local database, then uploads
|
|
31
|
+
everything to Unbent. It asks which Unbent instance to use the first time and remembers
|
|
32
|
+
the answer.
|
|
33
|
+
|
|
34
|
+
**Start with one notebook** to see the result before moving everything. The sync still
|
|
35
|
+
fetches your whole account — it is the upload that is scoped:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
evernote2unbent migrate -n "Some Notebook"
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Interrupted runs are safe to repeat: the sync is incremental, and notes that already
|
|
42
|
+
landed are skipped rather than duplicated.
|
|
43
|
+
|
|
44
|
+
### Doing the steps separately
|
|
45
|
+
|
|
46
|
+
`migrate` runs [evernote-backup](https://github.com/vzhd1701/evernote-backup) for you. If
|
|
47
|
+
you already use it, or want the ENEX files too, run the halves yourself:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
evernote-backup init-db
|
|
51
|
+
evernote-backup sync
|
|
52
|
+
evernote2unbent upload
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Re-running is safe
|
|
56
|
+
|
|
57
|
+
Unbent keys each note on a hash of its title and body, so a note that already landed is
|
|
58
|
+
skipped rather than duplicated. That makes an interrupted upload resumable by simply
|
|
59
|
+
repeating the command — and a note whose attachments failed partway gets only the missing
|
|
60
|
+
files on the next run.
|
|
61
|
+
|
|
62
|
+
Nothing here deletes or modifies anything in Evernote.
|
|
63
|
+
|
|
64
|
+
## Options
|
|
65
|
+
|
|
66
|
+
| Flag | Meaning |
|
|
67
|
+
| --- | --- |
|
|
68
|
+
| `-d, --database` | The database `evernote-backup sync` wrote (default `en_backup.db`) |
|
|
69
|
+
| `-n, --notebook` | Only this notebook. Repeatable |
|
|
70
|
+
| `-t, --tag` | Only notes with this tag. Repeatable |
|
|
71
|
+
| `--include-trash` | Include notes from Evernote's trash |
|
|
72
|
+
| `--url` | Instance for one command, without storing it |
|
|
73
|
+
|
|
74
|
+
## Signing in
|
|
75
|
+
|
|
76
|
+
`login` prints a short code and a link. Approving it in a browser you are already signed in
|
|
77
|
+
to grants an ordinary session — no password is typed into the terminal, and no long-lived
|
|
78
|
+
key is pasted from a settings page.
|
|
79
|
+
|
|
80
|
+
The token is stored in `~/.config/unbent/credentials.json` at mode `0600`, keyed by
|
|
81
|
+
instance so a token for one server is never sent to another. `logout` forgets it locally;
|
|
82
|
+
signing out everywhere in Unbent revokes it for real.
|
|
83
|
+
|
|
84
|
+
## Which instance
|
|
85
|
+
|
|
86
|
+
There is deliberately no default. A guessed instance means a forgotten flag can send a
|
|
87
|
+
migration to a server you did not choose, and that failure is silent, because uploading to
|
|
88
|
+
the wrong Unbent still succeeds.
|
|
89
|
+
|
|
90
|
+
The answer is stored in `~/.config/unbent/config.json` — plain JSON, mode `0644`, separate
|
|
91
|
+
from the credentials file so changing a URL never means opening one with a token in it.
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
evernote2unbent set-url https://unbent.app
|
|
95
|
+
evernote2unbent show-config
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
`$UNBENT_URL` overrides it for a shell session, `--url` for a single command.
|
|
99
|
+
|
|
100
|
+
## What gets converted
|
|
101
|
+
|
|
102
|
+
Notes arrive as Markdown. The conversion happens server-side in Unbent, which is why this
|
|
103
|
+
package does not implement one: Unbent's own importer already has a tested ENML converter,
|
|
104
|
+
and a second implementation here would drift from it.
|
|
105
|
+
|
|
106
|
+
Attachments upload separately as raw bytes and are linked from the note body by their
|
|
107
|
+
content hash, which is how an inline image ends up in the right place.
|
|
108
|
+
|
|
109
|
+
## Credit
|
|
110
|
+
|
|
111
|
+
The hard part — Evernote authentication, the Thrift API client, and incremental sync — is
|
|
112
|
+
[evernote-backup](https://github.com/vzhd1701/evernote-backup) by
|
|
113
|
+
[vzhd1701](https://github.com/vzhd1701), used here as a dependency rather than forked. This
|
|
114
|
+
package adds an uploader and a CLI on top of it and modifies none of it.
|
|
115
|
+
|
|
116
|
+
If you want ENEX files rather than a migration, use evernote-backup directly; it does that
|
|
117
|
+
well and this is not a replacement for it.
|
|
118
|
+
|
|
119
|
+
## License
|
|
120
|
+
|
|
121
|
+
MIT
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "evernote2unbent"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Move your Evernote notes into Unbent, without an ENEX file in between."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.10"
|
|
7
|
+
license = { text = "MIT" }
|
|
8
|
+
authors = [{ name = "C Deutsch" }]
|
|
9
|
+
keywords = ["evernote", "unbent", "enex", "migration", "export", "notes"]
|
|
10
|
+
classifiers = [
|
|
11
|
+
"Development Status :: 4 - Beta",
|
|
12
|
+
"Environment :: Console",
|
|
13
|
+
"Intended Audience :: End Users/Desktop",
|
|
14
|
+
"License :: OSI Approved :: MIT License",
|
|
15
|
+
"Programming Language :: Python :: 3",
|
|
16
|
+
"Topic :: Utilities",
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
dependencies = [
|
|
20
|
+
# The Evernote sync — account auth, incremental sync, and the local SQLite database
|
|
21
|
+
# this reads from. Depended on rather than forked: this package adds an uploader and a
|
|
22
|
+
# CLI and modifies none of it, so upstream fixes arrive with a version bump.
|
|
23
|
+
"evernote-backup>=1.14.0",
|
|
24
|
+
"click>=8.1",
|
|
25
|
+
"requests>=2.31",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
[project.urls]
|
|
29
|
+
Homepage = "https://github.com/cdeutsch/evernote2unbent"
|
|
30
|
+
Unbent = "https://unbent.app"
|
|
31
|
+
"evernote-backup" = "https://github.com/vzhd1701/evernote-backup"
|
|
32
|
+
|
|
33
|
+
[project.scripts]
|
|
34
|
+
evernote2unbent = "evernote2unbent.cli:main"
|
|
35
|
+
|
|
36
|
+
[dependency-groups]
|
|
37
|
+
test = ["pytest", "pytest-mock", "requests-mock"]
|
|
38
|
+
dev = ["ruff", "ty"]
|
|
39
|
+
|
|
40
|
+
[build-system]
|
|
41
|
+
requires = ["hatchling"]
|
|
42
|
+
build-backend = "hatchling.build"
|
|
43
|
+
|
|
44
|
+
[tool.hatch.build.targets.wheel]
|
|
45
|
+
packages = ["src/evernote2unbent"]
|
|
46
|
+
|
|
47
|
+
[tool.ruff]
|
|
48
|
+
# 90, matching evernote-backup, whose prose comments this code was written alongside.
|
|
49
|
+
line-length = 90
|
|
50
|
+
src = ["src", "tests"]
|
|
51
|
+
|
|
52
|
+
[tool.ruff.lint]
|
|
53
|
+
select = ["E", "F", "I", "UP", "B", "SIM", "RUF"]
|
|
54
|
+
|
|
55
|
+
[tool.ruff.lint.per-file-ignores]
|
|
56
|
+
"tests/*.py" = ["S", "PL"]
|