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.
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: overleaf-pull
3
- Version: 0.1.0
4
- Summary: Pull-only Overleaf project sync using Rookie + PyOverleaf
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
+ ![PyPI - Version](https://img.shields.io/pypi/v/overleaf-pull)
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 your browser cookies (Rookie) and lists them via PyOverleaf; syncs using Git.
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
- - Packages: rookiepy, pyoverleaf (installed via requirements.txt).
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
- # # Using uv (recommended)
39
- # uv currently not working!
40
- # uv sync
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
- First Run (setup)
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
- - Run once now:
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
- conda activate overleaf-sync
103
- conda install -c conda-forge pyside6
95
+ pip install 'overleaf-pull[qt]'
104
96
  overleaf-pull browser-login-qt
105
97
  ```
106
- - Pip/venv alternative:
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=DvTRO9kaeQIQAhZ70jOnDdO0QLpW6BVfQZzQRjE-OZM,35
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=VxAfKGpfcFO8XMDmFwHS-MB0yuF56B-Cd5Gcpd_Vg74,3069
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.1.0.dist-info/METADATA,sha256=5B_sU7VRfR7PIgHp2udLuGQyGtFSrGiGVI5zlVqNQI4,6349
12
- overleaf_pull-0.1.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
13
- overleaf_pull-0.1.0.dist-info/entry_points.txt,sha256=5eOqjySKRXlUJ5Xxudo4-JDn7HXkQYgodqXFx593Mns,57
14
- overleaf_pull-0.1.0.dist-info/RECORD,,
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.1.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 using Rookie from the selected browser/profile.
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
- if rookie_safari is None:
60
- raise RuntimeError("Safari cookie access requires rookiepy; install with 'uv add rookiepy' or 'pip install rookiepy'. On macOS, granting Full Disk Access to your terminal may be required.")
61
- # Rookie handles Safari paths internally
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 rookie_firefox is None:
66
- # Fallback to browsercookie for Firefox if rookiepy is unavailable
67
- if browsercookie is None:
68
- raise RuntimeError("Firefox cookie access requires rookiepy or browsercookie.")
69
- cj = browsercookie.firefox()
70
- jar: Dict[str, str] = {}
71
- for c in cj:
72
- domain = getattr(c, "domain", None)
73
- if domain and not any(d in domain for d in OVERLEAF_DOMAINS):
74
- continue
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 'safari' or 'firefox'.")
68
+ raise ValueError("Unsupported browser; choose 'firefox' or use Qt login.")