dbx-sync 0.2.0__tar.gz → 0.4.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.
@@ -6,9 +6,9 @@ This repository uses a single shared instruction file for coding agents.
6
6
 
7
7
  1. Sync dependencies with `uv sync --dev`.
8
8
  2. Implement code inside `src/dbx_sync/` using typed functions and small modules.
9
- 3. Add or update tests in `tests/` for each user-visible change.
10
- 4. Run `uv run ruff format .`, `uv run ruff check .`, `uv run ty check`, and `uv run pytest` before handing work back.
11
- 5. Use `uv build` and `uv publish` for packaging and release operations.
9
+ 3. Update README.md to document new or changed functionality.
10
+ 4. Add or update tests in `tests/` for each user-visible change.
11
+ 5. Run `uv run ruff format .`, `uv run ruff check .`, `uv run ty check`, and `uv run pytest` before handing work back.
12
12
 
13
13
  ## Guardrails
14
14
 
@@ -39,4 +39,3 @@ This repository uses a single shared instruction file for coding agents.
39
39
  - Add unit tests for critical paths and behavior changes.
40
40
  - Include edge-case coverage for empty inputs, invalid state, and error handling when those paths matter.
41
41
  - Keep tests readable and focused on behavior rather than implementation detail.
42
- - When adapting logic from another codebase, translate the relevant tests into this repo's current API instead of copying obsolete cases unchanged.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dbx-sync
3
- Version: 0.2.0
3
+ Version: 0.4.0
4
4
  Summary: Synchronize Databricks workspace content with a local directory.
5
5
  Project-URL: Repository, https://github.com/gramhagen/dbx-sync
6
6
  Author: gramhagen
@@ -22,7 +22,7 @@ Description-Content-Type: text/markdown
22
22
 
23
23
  Are you tired of bouncing between the Databricks workspace UI and your local editor, copying changes by hand, and pretending that counts as a workflow? Well now there's `dbx-sync`.
24
24
 
25
- `dbx-sync` keeps a single Databricks workspace folder and a single local directory in sync so you can work with your favorite tools and still stay aligned with what is running in Databricks.
25
+ `dbx-sync` keeps a Databricks workspace folder or file and a local directory or file in sync so you can work with your favorite tools and still stay aligned with what is running in Databricks.
26
26
 
27
27
  Build locally, run in Databricks, tweak it there, then jump back to local coding. Skip the usual copy-paste ritual or one-way imports to weird folders.
28
28
 
@@ -32,9 +32,10 @@ Worried about losing files? `dbx-sync` does not delete files locally or remotely
32
32
 
33
33
  Current scope notes:
34
34
 
35
- - Sync is limited to a single local folder and a single Databricks workspace folder.
35
+ - Sync is limited to a single local folder/workspace folder pair or one local/workspace file pair.
36
36
  - File and folder discovery is not recursive.
37
37
  - Local tracking currently covers notebook files with Databricks notebook extensions: `.py`, `.sql`, `.scala`, `.r`, and `.ipynb`.
38
+ - When syncing a single local file, notebook extensions are imported as notebooks and other files are imported as workspace files.
38
39
 
39
40
  ## Prerequisites
40
41
 
@@ -83,6 +84,24 @@ Sync a single workspace folder with a single local folder (one-time):
83
84
  dbx-sync ./local-project /Workspace/Users/me/project
84
85
  ```
85
86
 
87
+ Sync a single local file to a workspace folder, using the source filename for the target object:
88
+
89
+ ```bash
90
+ dbx-sync ./local-project/notebook.py /Workspace/Users/me/project
91
+ ```
92
+
93
+ Sync a single workspace file or notebook to a local folder, using the source filename locally:
94
+
95
+ ```bash
96
+ dbx-sync ./local-project /Workspace/Users/me/project/notebook
97
+ ```
98
+
99
+ Sync explicit local and workspace file paths:
100
+
101
+ ```bash
102
+ dbx-sync ./local-project/notebook.py /Workspace/Users/me/project/notebook
103
+ ```
104
+
86
105
  Preview actions without applying them:
87
106
 
88
107
  ```bash
@@ -95,6 +114,19 @@ Continuously watch and resync (default polling happens every second):
95
114
  dbx-sync ./local-project /Workspace/Users/me/project --watch
96
115
  ```
97
116
 
117
+ Use `--force` to clear saved sync state before a fresh pass. This can be useful to handle conflicts.
118
+ Pro-tip: Add --dry-run to check force behavior before running it for real.
119
+
120
+ Force options are mutually exclusive and only apply to a single sync pass:
121
+
122
+ - `--force` clears saved sync state before comparing local and remote files.
123
+ - `--force-upload` uploads matching local files even when saved sync state would otherwise skip them.
124
+ - `--force-download` downloads matching remote files even when saved sync state would otherwise skip them.
125
+
126
+ ```bash
127
+ dbx-sync ./local-project /Workspace/Users/me/project --force
128
+ ```
129
+
98
130
  Override optional settings when needed:
99
131
 
100
132
  ```bash
@@ -102,10 +134,9 @@ dbx-sync ./local-project /Workspace/Users/me/project \
102
134
  --profile WORKSPACE \
103
135
  --poll-interval 5 \
104
136
  --log-level DEBUG \
105
- --force
106
137
  ```
107
138
 
108
- Use `--force` to clear saved sync state before a fresh pass.
139
+ Watch mode cannot be combined with force options or dry-run mode. Use `--watch` for continuous syncing, or use `--dry-run`, `--force`, `--force-upload`, and `--force-download` for one-time sync passes.
109
140
 
110
141
  If your local directory does not exist, the tool will attempt to create it for you (when not in dry-run mode).
111
142
 
@@ -11,7 +11,7 @@
11
11
 
12
12
  Are you tired of bouncing between the Databricks workspace UI and your local editor, copying changes by hand, and pretending that counts as a workflow? Well now there's `dbx-sync`.
13
13
 
14
- `dbx-sync` keeps a single Databricks workspace folder and a single local directory in sync so you can work with your favorite tools and still stay aligned with what is running in Databricks.
14
+ `dbx-sync` keeps a Databricks workspace folder or file and a local directory or file in sync so you can work with your favorite tools and still stay aligned with what is running in Databricks.
15
15
 
16
16
  Build locally, run in Databricks, tweak it there, then jump back to local coding. Skip the usual copy-paste ritual or one-way imports to weird folders.
17
17
 
@@ -21,9 +21,10 @@ Worried about losing files? `dbx-sync` does not delete files locally or remotely
21
21
 
22
22
  Current scope notes:
23
23
 
24
- - Sync is limited to a single local folder and a single Databricks workspace folder.
24
+ - Sync is limited to a single local folder/workspace folder pair or one local/workspace file pair.
25
25
  - File and folder discovery is not recursive.
26
26
  - Local tracking currently covers notebook files with Databricks notebook extensions: `.py`, `.sql`, `.scala`, `.r`, and `.ipynb`.
27
+ - When syncing a single local file, notebook extensions are imported as notebooks and other files are imported as workspace files.
27
28
 
28
29
  ## Prerequisites
29
30
 
@@ -72,6 +73,24 @@ Sync a single workspace folder with a single local folder (one-time):
72
73
  dbx-sync ./local-project /Workspace/Users/me/project
73
74
  ```
74
75
 
76
+ Sync a single local file to a workspace folder, using the source filename for the target object:
77
+
78
+ ```bash
79
+ dbx-sync ./local-project/notebook.py /Workspace/Users/me/project
80
+ ```
81
+
82
+ Sync a single workspace file or notebook to a local folder, using the source filename locally:
83
+
84
+ ```bash
85
+ dbx-sync ./local-project /Workspace/Users/me/project/notebook
86
+ ```
87
+
88
+ Sync explicit local and workspace file paths:
89
+
90
+ ```bash
91
+ dbx-sync ./local-project/notebook.py /Workspace/Users/me/project/notebook
92
+ ```
93
+
75
94
  Preview actions without applying them:
76
95
 
77
96
  ```bash
@@ -84,6 +103,19 @@ Continuously watch and resync (default polling happens every second):
84
103
  dbx-sync ./local-project /Workspace/Users/me/project --watch
85
104
  ```
86
105
 
106
+ Use `--force` to clear saved sync state before a fresh pass. This can be useful to handle conflicts.
107
+ Pro-tip: Add --dry-run to check force behavior before running it for real.
108
+
109
+ Force options are mutually exclusive and only apply to a single sync pass:
110
+
111
+ - `--force` clears saved sync state before comparing local and remote files.
112
+ - `--force-upload` uploads matching local files even when saved sync state would otherwise skip them.
113
+ - `--force-download` downloads matching remote files even when saved sync state would otherwise skip them.
114
+
115
+ ```bash
116
+ dbx-sync ./local-project /Workspace/Users/me/project --force
117
+ ```
118
+
87
119
  Override optional settings when needed:
88
120
 
89
121
  ```bash
@@ -91,10 +123,9 @@ dbx-sync ./local-project /Workspace/Users/me/project \
91
123
  --profile WORKSPACE \
92
124
  --poll-interval 5 \
93
125
  --log-level DEBUG \
94
- --force
95
126
  ```
96
127
 
97
- Use `--force` to clear saved sync state before a fresh pass.
128
+ Watch mode cannot be combined with force options or dry-run mode. Use `--watch` for continuous syncing, or use `--dry-run`, `--force`, `--force-upload`, and `--force-download` for one-time sync passes.
98
129
 
99
130
  If your local directory does not exist, the tool will attempt to create it for you (when not in dry-run mode).
100
131
 
@@ -2,4 +2,4 @@
2
2
 
3
3
  __all__ = ["__version__"]
4
4
 
5
- __version__ = "0.2.0"
5
+ __version__ = "0.4.0"
@@ -4,7 +4,8 @@ import argparse
4
4
  from collections.abc import Sequence
5
5
  from pathlib import Path
6
6
 
7
- from dbx_sync.sync import run_sync
7
+ from dbx_sync import __version__
8
+ from dbx_sync.sync import ForceType, run_sync
8
9
 
9
10
  DEFAULT_POLL_INTERVAL_SECONDS = 1
10
11
  LOG_LEVELS = ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]
@@ -29,10 +30,11 @@ def main(argv: Sequence[str] | None = None) -> int:
29
30
  """
30
31
  parser = argparse.ArgumentParser(
31
32
  prog="dbx-sync",
32
- description="Synchronize Databricks workspace files to a local directory.",
33
+ description="Synchronize Databricks workspace files with a local path.",
33
34
  )
34
- parser.add_argument("local_dir", help="Local directory to sync")
35
- parser.add_argument("workspace", help="Databricks workspace folder to sync")
35
+ parser.add_argument("-v", "--version", action="version", version=f"%(prog)s {__version__}")
36
+ parser.add_argument("local_dir", help="Local file or directory to sync")
37
+ parser.add_argument("workspace", help="Databricks workspace file or folder to sync")
36
38
  parser.add_argument("--profile", default="DEFAULT", help="Databricks CLI profile name")
37
39
  parser.add_argument(
38
40
  "-p",
@@ -60,14 +62,35 @@ def main(argv: Sequence[str] | None = None) -> int:
60
62
  action="store_true",
61
63
  help="Watch for changes and sync continuously",
62
64
  )
63
- parser.add_argument(
65
+ force_group = parser.add_mutually_exclusive_group()
66
+ force_group.add_argument(
64
67
  "-f",
65
68
  "--force",
66
69
  action="store_true",
67
70
  help="Force a refresh by clearing saved sync state before running",
68
71
  )
72
+ force_group.add_argument(
73
+ "-fu",
74
+ "--force-upload",
75
+ action="store_true",
76
+ help="Force upload of all local files, ignoring sync state",
77
+ )
78
+ force_group.add_argument(
79
+ "-fd",
80
+ "--force-download",
81
+ action="store_true",
82
+ help="Force download of all remote files, ignoring sync state",
83
+ )
69
84
  args = parser.parse_args(argv)
70
85
 
86
+ force_type = None
87
+ if args.force:
88
+ force_type = ForceType.CLEAR
89
+ elif args.force_upload:
90
+ force_type = ForceType.UPLOAD
91
+ elif args.force_download:
92
+ force_type = ForceType.DOWNLOAD
93
+
71
94
  try:
72
95
  return run_sync(
73
96
  local_dir=Path(args.local_dir).expanduser().resolve(),
@@ -77,7 +100,7 @@ def main(argv: Sequence[str] | None = None) -> int:
77
100
  log_level=args.log_level,
78
101
  dry_run=args.dry_run,
79
102
  watch=args.watch,
80
- force=args.force,
103
+ force_type=force_type,
81
104
  )
82
105
  except RuntimeError as exc:
83
106
  # print user-friendly instructions if error is reauthentication-related, otherwise re-raise