overleaf-pull 0.1.0__py3-none-any.whl → 0.2.0__py3-none-any.whl
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.
- {overleaf_pull-0.1.0.dist-info → overleaf_pull-0.2.0.dist-info}/METADATA +39 -39
- {overleaf_pull-0.1.0.dist-info → overleaf_pull-0.2.0.dist-info}/RECORD +6 -6
- overleaf_sync/__init__.py +1 -1
- overleaf_sync/cookies.py +16 -30
- {overleaf_pull-0.1.0.dist-info → overleaf_pull-0.2.0.dist-info}/WHEEL +0 -0
- {overleaf_pull-0.1.0.dist-info → overleaf_pull-0.2.0.dist-info}/entry_points.txt +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: overleaf-pull
|
|
3
|
-
Version: 0.
|
|
4
|
-
Summary: Pull-only Overleaf project sync using
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Pull-only Overleaf project sync using PyOverleaf
|
|
5
5
|
Project-URL: Homepage, https://github.com/LeanderK/overleaf_sync
|
|
6
6
|
Project-URL: Issues, https://github.com/LeanderK/overleaf_sync/issues
|
|
7
7
|
Author: Leander Kurscheidt
|
|
@@ -15,46 +15,44 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
15
15
|
Requires-Python: >=3.10
|
|
16
16
|
Requires-Dist: browsercookie>=0.7
|
|
17
17
|
Requires-Dist: pyoverleaf>=0.1.7
|
|
18
|
-
Requires-Dist: rookiepy==0.5.4
|
|
19
18
|
Provides-Extra: qt
|
|
20
19
|
Requires-Dist: pyside6>=6.6; extra == 'qt'
|
|
21
20
|
Description-Content-Type: text/markdown
|
|
22
21
|
|
|
23
22
|
# Overleaf Pull-Only Sync CLI
|
|
23
|
+

|
|
24
|
+
|
|
25
|
+
Quick Start (users)
|
|
26
|
+
```bash
|
|
27
|
+
# Install with Qt login support
|
|
28
|
+
pip install 'overleaf-pull[qt]'
|
|
29
|
+
|
|
30
|
+
# Guided setup and background install
|
|
31
|
+
overleaf-pull init --install
|
|
32
|
+
```
|
|
24
33
|
|
|
25
34
|
Overview
|
|
26
35
|
- Pull-only tool that periodically clones/pulls your latest Overleaf projects into a local directory.
|
|
27
|
-
- Discovers projects via
|
|
36
|
+
- Discovers projects via cookies captured during setup (Qt login recommended) or manual paste; Firefox cookies can be read automatically.
|
|
37
|
+
- Lists projects via PyOverleaf; syncs using Git.
|
|
28
38
|
- Runs in the background as a macOS LaunchAgent or Linux systemd user timer.
|
|
29
39
|
|
|
30
40
|
Requirements
|
|
31
41
|
- macOS or Linux with Git installed.
|
|
32
42
|
- Python 3.10+.
|
|
33
|
-
-
|
|
43
|
+
- Dependencies are installed automatically via pip. Optional extras: `[qt]` for PySide6 (Qt login).
|
|
34
44
|
- Overleaf Git integration enabled on your account to allow cloning/pulling via git.overleaf.com.
|
|
35
45
|
|
|
36
|
-
Install
|
|
46
|
+
Install (pip)
|
|
37
47
|
```bash
|
|
38
|
-
|
|
39
|
-
#
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
# Or using conda
|
|
43
|
-
conda env create -f environment.yml
|
|
44
|
-
conda activate overleaf-sync
|
|
45
|
-
|
|
46
|
-
# Or using pip/venv
|
|
47
|
-
python3 -m venv .venv
|
|
48
|
-
. .venv/bin/activate
|
|
49
|
-
pip install -r requirements.txt
|
|
48
|
+
pip install overleaf-pull
|
|
49
|
+
# Optional Qt login support:
|
|
50
|
+
pip install 'overleaf-pull[qt]'
|
|
50
51
|
```
|
|
51
52
|
|
|
52
|
-
|
|
53
|
+
Quick Setup
|
|
53
54
|
```bash
|
|
54
55
|
overleaf-pull init --install
|
|
55
|
-
# If the console script isn't found, use:
|
|
56
|
-
# uv currently not working!
|
|
57
|
-
# uv run python -m overleaf_sync.cli init --install
|
|
58
56
|
```
|
|
59
57
|
- Prompts for the base directory, interval (1h/12h/24h), count (default 10), browser/profile, and host (default www.overleaf.com).
|
|
60
58
|
- Offers a Qt browser login to capture cookies automatically (default Yes if PySide6 is installed). Falls back to optional manual cookie paste.
|
|
@@ -63,17 +61,13 @@ overleaf-pull init --install
|
|
|
63
61
|
- Runs a validation sync before installing the scheduler, to confirm access.
|
|
64
62
|
|
|
65
63
|
Manual Commands
|
|
66
|
-
|
|
64
|
+
Run once now:
|
|
67
65
|
```bash
|
|
68
66
|
overleaf-pull run-once
|
|
69
|
-
# Or via uv:
|
|
70
|
-
uv run python -m overleaf_sync.cli run-once
|
|
71
67
|
```
|
|
72
68
|
- Manual sync (with optional overrides):
|
|
73
69
|
```bash
|
|
74
70
|
overleaf-pull sync --count 5 --base-dir ~/Overleaf --browser firefox
|
|
75
|
-
# Or via uv:
|
|
76
|
-
uv run python -m overleaf_sync.cli sync --count 5 --base-dir ~/Overleaf --browser firefox
|
|
77
71
|
```
|
|
78
72
|
- Store or clear cookies in config:
|
|
79
73
|
- Folder naming preference:
|
|
@@ -97,18 +91,11 @@ Required cookies
|
|
|
97
91
|
|
|
98
92
|
Qt browser login (optional)
|
|
99
93
|
- Use a built-in Qt browser to log in and auto-capture cookies.
|
|
100
|
-
- Conda (recommended on macOS/Linux):
|
|
101
94
|
```bash
|
|
102
|
-
|
|
103
|
-
conda install -c conda-forge pyside6
|
|
95
|
+
pip install 'overleaf-pull[qt]'
|
|
104
96
|
overleaf-pull browser-login-qt
|
|
105
97
|
```
|
|
106
|
-
|
|
107
|
-
```bash
|
|
108
|
-
pip install PySide6
|
|
109
|
-
python -m overleaf_sync.cli browser-login-qt
|
|
110
|
-
```
|
|
111
|
-
During setup, if PySide6 is present, the tool will offer the Qt login flow by default.
|
|
98
|
+
During setup, if PySide6 is present, the tool offers the Qt login flow by default.
|
|
112
99
|
|
|
113
100
|
Git authentication token
|
|
114
101
|
- Overleaf requires a Git auth token for `git clone`/`git pull`.
|
|
@@ -129,9 +116,6 @@ overleaf-pull status
|
|
|
129
116
|
```bash
|
|
130
117
|
overleaf-pull install-scheduler
|
|
131
118
|
overleaf-pull uninstall-scheduler
|
|
132
|
-
# Or via uv:
|
|
133
|
-
uv run python -m overleaf_sync.cli install-scheduler
|
|
134
|
-
uv run python -m overleaf_sync.cli uninstall-scheduler
|
|
135
119
|
```
|
|
136
120
|
Installing the scheduler is idempotent: it uninstalls any existing instance first, then reinstalls to ensure only one scheduler is active.
|
|
137
121
|
Publish to PyPI (CI)
|
|
@@ -176,3 +160,19 @@ overleaf-pull set-git-token
|
|
|
176
160
|
```
|
|
177
161
|
- Without a token, new clones will fail with 403; existing repos may also fail if their remotes lack the token. Prompts are disabled in background.
|
|
178
162
|
|
|
163
|
+
Development
|
|
164
|
+
- Create a local environment and install from source:
|
|
165
|
+
```bash
|
|
166
|
+
python3 -m venv .venv
|
|
167
|
+
. .venv/bin/activate
|
|
168
|
+
pip install -e .
|
|
169
|
+
# Optional Qt support
|
|
170
|
+
pip install PySide6
|
|
171
|
+
```
|
|
172
|
+
- Conda alternative:
|
|
173
|
+
```bash
|
|
174
|
+
conda env create -f environment.yml
|
|
175
|
+
conda activate overleaf-sync
|
|
176
|
+
pip install -e .
|
|
177
|
+
```
|
|
178
|
+
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
overleaf_sync/__init__.py,sha256=
|
|
1
|
+
overleaf_sync/__init__.py,sha256=1UV6VBKvPJ6ZAzarRkCxLMz8Farih3XKEFeEV1m76a4,35
|
|
2
2
|
overleaf_sync/cli.py,sha256=5KlQAs-lbBBv2edSak8ucdKwhX2FrcBUkvMfRcP-pb8,16209
|
|
3
3
|
overleaf_sync/config.py,sha256=76Fn4jLm7k0hEt-T_EUGF2XazDQNzTqxd-rU0HUjMPU,6772
|
|
4
|
-
overleaf_sync/cookies.py,sha256=
|
|
4
|
+
overleaf_sync/cookies.py,sha256=VUB6CTM-Vp4JrredK3VUjl22r09zoKE8Z28_Q9Tu5TU,2384
|
|
5
5
|
overleaf_sync/git_ops.py,sha256=O2BTgFSRqzTERBDsFlQ-d_K7IUZFIcZEtUHEGft_BEY,6131
|
|
6
6
|
overleaf_sync/olbrowser_login.py,sha256=hLDlpGqfE4jRVh3FjC7uEyI5rnzZl8eFyVqMJITZ35w,2749
|
|
7
7
|
overleaf_sync/overleaf_api.py,sha256=jFAy91MAji3KiNCFtRxYE6707BlRZEHLryiDMALFzr0,1613
|
|
8
8
|
overleaf_sync/projects.py,sha256=n0V5D-1jJ7V1G8klikJVEfx2SkZj3I6q_VaPDWWR_B8,500
|
|
9
9
|
overleaf_sync/scheduler.py,sha256=qRZcpq-jzF4Ko6QEs-OKDw7kteLqoGG3lL25e6cAImA,4012
|
|
10
10
|
overleaf_sync/sync.py,sha256=Rv76Em39ZRVesS7aSIOsh1w-l3ER2mKOylUJ4KKY4Js,4252
|
|
11
|
-
overleaf_pull-0.
|
|
12
|
-
overleaf_pull-0.
|
|
13
|
-
overleaf_pull-0.
|
|
14
|
-
overleaf_pull-0.
|
|
11
|
+
overleaf_pull-0.2.0.dist-info/METADATA,sha256=vq_DQRmqLr91gwhQg6WKFthO5HLhntAuk_DurkinXtQ,6212
|
|
12
|
+
overleaf_pull-0.2.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
13
|
+
overleaf_pull-0.2.0.dist-info/entry_points.txt,sha256=5eOqjySKRXlUJ5Xxudo4-JDn7HXkQYgodqXFx593Mns,57
|
|
14
|
+
overleaf_pull-0.2.0.dist-info/RECORD,,
|
overleaf_sync/__init__.py
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
__all__ = []
|
|
2
|
-
__version__ = "0.
|
|
2
|
+
__version__ = "0.2.0"
|
overleaf_sync/cookies.py
CHANGED
|
@@ -3,13 +3,6 @@ import shutil
|
|
|
3
3
|
import tempfile
|
|
4
4
|
from typing import Dict, List
|
|
5
5
|
|
|
6
|
-
try:
|
|
7
|
-
from rookiepy import safari as rookie_safari
|
|
8
|
-
from rookiepy import firefox as rookie_firefox
|
|
9
|
-
except Exception: # pragma: no cover
|
|
10
|
-
rookie_safari = None
|
|
11
|
-
rookie_firefox = None
|
|
12
|
-
|
|
13
6
|
try:
|
|
14
7
|
import browsercookie # type: ignore
|
|
15
8
|
except Exception: # pragma: no cover
|
|
@@ -51,32 +44,25 @@ def parse_cookie_string(s: str) -> Dict[str, str]:
|
|
|
51
44
|
|
|
52
45
|
|
|
53
46
|
def load_overleaf_cookies(browser: str, profile: str | None = None) -> Dict[str, str]:
|
|
54
|
-
"""Load Overleaf cookies
|
|
47
|
+
"""Load Overleaf cookies from the selected browser/profile.
|
|
55
48
|
|
|
56
49
|
Returns a dict of cookie name -> value suitable for PyOverleaf Api.login_from_cookies.
|
|
50
|
+
Note: Safari cookie loading via code is no longer supported; use Qt login or paste cookies.
|
|
57
51
|
"""
|
|
58
52
|
if browser == "safari":
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
cookies = rookie_safari(OVERLEAF_DOMAINS)
|
|
63
|
-
return _to_cookie_dict(cookies)
|
|
53
|
+
raise RuntimeError(
|
|
54
|
+
"Safari cookie access is not supported without Qt. Please run 'overleaf-pull browser-login-qt' or paste cookies via 'overleaf-pull set-cookie'."
|
|
55
|
+
)
|
|
64
56
|
elif browser == "firefox":
|
|
65
|
-
if
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
for
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
jar[c.name] = c.value
|
|
76
|
-
return jar
|
|
77
|
-
# Firefox may lock cookies.sqlite; Rookie generally reads via its own logic,
|
|
78
|
-
# but if needed, we can copy the profile dir to a temp path.
|
|
79
|
-
cookies = rookie_firefox(OVERLEAF_DOMAINS)
|
|
80
|
-
return _to_cookie_dict(cookies)
|
|
57
|
+
if browsercookie is None:
|
|
58
|
+
raise RuntimeError("Firefox cookie access requires the 'browsercookie' package.")
|
|
59
|
+
cj = browsercookie.firefox()
|
|
60
|
+
jar: Dict[str, str] = {}
|
|
61
|
+
for c in cj:
|
|
62
|
+
domain = getattr(c, "domain", None)
|
|
63
|
+
if domain and not any(d in domain for d in OVERLEAF_DOMAINS):
|
|
64
|
+
continue
|
|
65
|
+
jar[c.name] = c.value
|
|
66
|
+
return jar
|
|
81
67
|
else:
|
|
82
|
-
raise ValueError("Unsupported browser; choose '
|
|
68
|
+
raise ValueError("Unsupported browser; choose 'firefox' or use Qt login.")
|
|
File without changes
|
|
File without changes
|