cubething_psync 0.1.0.dev5__tar.gz → 0.1.0.dev7__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.
Files changed (21) hide show
  1. {cubething_psync-0.1.0.dev5 → cubething_psync-0.1.0.dev7}/PKG-INFO +2 -1
  2. {cubething_psync-0.1.0.dev5 → cubething_psync-0.1.0.dev7}/README.md +1 -0
  3. {cubething_psync-0.1.0.dev5 → cubething_psync-0.1.0.dev7}/pyproject.toml +1 -1
  4. {cubething_psync-0.1.0.dev5 → cubething_psync-0.1.0.dev7}/src/client/args.py +18 -6
  5. {cubething_psync-0.1.0.dev5 → cubething_psync-0.1.0.dev7}/src/client/main.py +23 -12
  6. {cubething_psync-0.1.0.dev5 → cubething_psync-0.1.0.dev7}/src/cubething_psync.egg-info/PKG-INFO +2 -1
  7. {cubething_psync-0.1.0.dev5 → cubething_psync-0.1.0.dev7}/src/server/main.py +8 -9
  8. {cubething_psync-0.1.0.dev5 → cubething_psync-0.1.0.dev7}/LICENSE +0 -0
  9. {cubething_psync-0.1.0.dev5 → cubething_psync-0.1.0.dev7}/setup.cfg +0 -0
  10. {cubething_psync-0.1.0.dev5 → cubething_psync-0.1.0.dev7}/src/client/__init__.py +0 -0
  11. {cubething_psync-0.1.0.dev5 → cubething_psync-0.1.0.dev7}/src/client/__main__.py +0 -0
  12. {cubething_psync-0.1.0.dev5 → cubething_psync-0.1.0.dev7}/src/common/__init__.py +0 -0
  13. {cubething_psync-0.1.0.dev5 → cubething_psync-0.1.0.dev7}/src/common/data.py +0 -0
  14. {cubething_psync-0.1.0.dev5 → cubething_psync-0.1.0.dev7}/src/common/log.py +0 -0
  15. {cubething_psync-0.1.0.dev5 → cubething_psync-0.1.0.dev7}/src/cubething_psync.egg-info/SOURCES.txt +0 -0
  16. {cubething_psync-0.1.0.dev5 → cubething_psync-0.1.0.dev7}/src/cubething_psync.egg-info/dependency_links.txt +0 -0
  17. {cubething_psync-0.1.0.dev5 → cubething_psync-0.1.0.dev7}/src/cubething_psync.egg-info/entry_points.txt +0 -0
  18. {cubething_psync-0.1.0.dev5 → cubething_psync-0.1.0.dev7}/src/cubething_psync.egg-info/requires.txt +0 -0
  19. {cubething_psync-0.1.0.dev5 → cubething_psync-0.1.0.dev7}/src/cubething_psync.egg-info/top_level.txt +0 -0
  20. {cubething_psync-0.1.0.dev5 → cubething_psync-0.1.0.dev7}/src/server/__init__.py +0 -0
  21. {cubething_psync-0.1.0.dev5 → cubething_psync-0.1.0.dev7}/src/server/__main__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cubething_psync
3
- Version: 0.1.0.dev5
3
+ Version: 0.1.0.dev7
4
4
  Summary: Simple project synchronization tool.
5
5
  Author-email: ada mandala <ada@cubething.dev>
6
6
  License-Expression: MIT
@@ -20,6 +20,7 @@ Dynamic: license-file
20
20
  </div>
21
21
 
22
22
  [![readthedocs](https://app.readthedocs.org/projects/psync/badge/?version=latest)](https://psync.readthedocs.io/en/latest)
23
+ [![PyPI - Version](https://img.shields.io/pypi/v/cubething_psync)](https://pypi.org/project/cubething_psync)
23
24
 
24
25
  **psync** is a simple tool to sync your project over SSH. It consists of a
25
26
  client and server.
@@ -3,6 +3,7 @@
3
3
  </div>
4
4
 
5
5
  [![readthedocs](https://app.readthedocs.org/projects/psync/badge/?version=latest)](https://psync.readthedocs.io/en/latest)
6
+ [![PyPI - Version](https://img.shields.io/pypi/v/cubething_psync)](https://pypi.org/project/cubething_psync)
6
7
 
7
8
  **psync** is a simple tool to sync your project over SSH. It consists of a
8
9
  client and server.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "cubething_psync"
3
- version = "0.1.0.dev5"
3
+ version = "0.1.0.dev7"
4
4
  description = "Simple project synchronization tool."
5
5
  authors = [{name = "ada mandala", email="ada@cubething.dev"}]
6
6
  readme = "README.md"
@@ -10,14 +10,28 @@ from common.data import deserialize_env
10
10
  @dataclass
11
11
  class Args:
12
12
  target_path: str
13
- dest_path: str
14
13
  extra: list[str]
15
14
  env: dict[str, str]
16
15
  args: list[str]
17
16
 
18
17
 
19
18
  parser = argparse.ArgumentParser(
20
- prog="psync-client", description="Client for the psync server."
19
+ prog="psync-client",
20
+ usage="""\
21
+ Client for the psync server.
22
+
23
+ In addition to the options below, the client is configurable through environment
24
+ variables.
25
+
26
+ Variable | Default
27
+ ------------------+-------------------------------
28
+ PSYNC_SERVER_IP | 127.0.0.1
29
+ PSYNC_SERVER_PORT | 5000
30
+ PSYNC_SSH_PORT | 5022
31
+ PSYNC_SERVER_DEST | /app/rsync/
32
+ PSYNC_SSH_USER | <unset>
33
+ PSYNC_CERT_PATH | ~/.local/share/psync/cert.pem
34
+ """,
21
35
  )
22
36
  _action = parser.add_argument(
23
37
  "--path",
@@ -42,6 +56,8 @@ _action = parser.add_argument(
42
56
 
43
57
  SERVER_IP: str = os.environ.get("PSYNC_SERVER_IP", "127.0.0.1")
44
58
  SERVER_PORT: int = int(os.environ.get("PSYNC_SERVER_PORT", "5000"))
59
+ SERVER_SSH_PORT: int = int(os.environ.get("PSYNC_SSH_PORT", "5022"))
60
+ SERVER_DEST: str = os.environ.get("PSYNC_SERVER_DEST", "/app/rsync")
45
61
  USER: str = os.environ.get("PSYNC_SSH_USER", "")
46
62
  SSL_CERT_PATH: str = os.environ.get("PSYNC_CERT_PATH", "~/.local/share/psync/cert.pem")
47
63
 
@@ -55,9 +71,6 @@ def parse_args() -> Args:
55
71
  logging.error(f"Could not file at {target_path}")
56
72
  exit(1)
57
73
 
58
- val_hash = hash(os.getcwd())
59
- dest_path = f"~/.local/share/psync/{val_hash}/"
60
-
61
74
  extra: list[str] = []
62
75
  extra_raw = args.get("extra")
63
76
  if extra_raw is not None:
@@ -75,7 +88,6 @@ def parse_args() -> Args:
75
88
 
76
89
  return Args(
77
90
  target_path=str(target_path),
78
- dest_path=dest_path,
79
91
  extra=extra or [],
80
92
  env=env,
81
93
  args=client_args,
@@ -3,6 +3,7 @@ psync client
3
3
  """
4
4
 
5
5
  import asyncio
6
+ import hashlib
6
7
  import os
7
8
  import pathlib
8
9
  import signal
@@ -21,7 +22,16 @@ from common.data import (
21
22
  )
22
23
  import logging
23
24
  from common.log import InterceptHandler
24
- from client.args import SERVER_IP, SERVER_PORT, USER, SSL_CERT_PATH, Args, parse_args
25
+ from client.args import (
26
+ SERVER_IP,
27
+ SERVER_PORT,
28
+ SERVER_SSH_PORT,
29
+ USER,
30
+ SSL_CERT_PATH,
31
+ SERVER_DEST,
32
+ Args,
33
+ parse_args,
34
+ )
25
35
 
26
36
 
27
37
  class PsyncClient:
@@ -49,7 +59,9 @@ class PsyncClient:
49
59
  Default: 127.0.0.1
50
60
  PSYNC_SERVER_PORT: The port of the server instance.
51
61
  Default: 5000
52
- PSYNC_SSH_USER: The SSH user for rsync.
62
+ PSYNC_SSH_PORT: The server instance's SSH port.
63
+ Default: 5001
64
+ PSYNC_SSH_USER: The server instance's SSH user.
53
65
  Default: Unset. Will use the default ssh user.
54
66
  PSYNC_CERT_PATH: Path to the SSL certificate. Used to trust self-signed certs. Should
55
67
  match the server's certificate.
@@ -87,7 +99,6 @@ class PsyncClient:
87
99
  ssl_ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
88
100
  ssl_ctx.load_verify_locations(pathlib.Path(SSL_CERT_PATH).expanduser())
89
101
  ssl_ctx.check_hostname = False # not ideal
90
- print(ssl_ctx.get_ca_certs())
91
102
  async with websockets.connect(
92
103
  f"wss://{SERVER_IP}:{SERVER_PORT}", ssl=ssl_ctx
93
104
  ) as ws:
@@ -129,13 +140,10 @@ class PsyncClient:
129
140
  logging.warning(f"Got unknown request {resp}")
130
141
 
131
142
 
132
- def __rsync(args: Args):
143
+ def __rsync(project_hash: str, args: Args):
133
144
  """Runs rsync."""
134
- if USER != "":
135
- user = f"{USER}@"
136
- else:
137
- user = ""
138
- url = f"{user}{SERVER_IP}:{args.dest_path}"
145
+ user = f"{USER}@" if USER != "" else ""
146
+ url = f"ssh://{user}{SERVER_IP}:{SERVER_SSH_PORT}/{SERVER_DEST}/{project_hash}/"
139
147
  rsync_args = [
140
148
  "rsync",
141
149
  "-avzr",
@@ -160,11 +168,14 @@ def main():
160
168
  log_level = os.environ.get("PSYNC_LOG", "INFO").upper()
161
169
  logging.basicConfig(handlers=[InterceptHandler()], level=log_level, force=True)
162
170
 
171
+ project_hash = hashlib.blake2s(os.getcwd().encode(), digest_size=8).hexdigest()
163
172
  args = parse_args()
164
- __rsync(args)
173
+ __rsync(project_hash, args)
165
174
 
166
- client_path = pathlib.Path(f"{args.dest_path}/{os.path.basename(args.target_path)}")
167
- client = PsyncClient(args=args.args, env=args.env, path=client_path)
175
+ dest_path = pathlib.Path(
176
+ f"{SERVER_DEST}/{project_hash}/{os.path.basename(args.target_path)}"
177
+ )
178
+ client = PsyncClient(args=args.args, env=args.env, path=dest_path)
168
179
  asyncio.run(client.run())
169
180
 
170
181
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cubething_psync
3
- Version: 0.1.0.dev5
3
+ Version: 0.1.0.dev7
4
4
  Summary: Simple project synchronization tool.
5
5
  Author-email: ada mandala <ada@cubething.dev>
6
6
  License-Expression: MIT
@@ -20,6 +20,7 @@ Dynamic: license-file
20
20
  </div>
21
21
 
22
22
  [![readthedocs](https://app.readthedocs.org/projects/psync/badge/?version=latest)](https://psync.readthedocs.io/en/latest)
23
+ [![PyPI - Version](https://img.shields.io/pypi/v/cubething_psync)](https://pypi.org/project/cubething_psync)
23
24
 
24
25
  **psync** is a simple tool to sync your project over SSH. It consists of a
25
26
  client and server.
@@ -34,12 +34,6 @@ import logging
34
34
  from common.log import InterceptHandler
35
35
 
36
36
 
37
- def __get_host(ws: ServerConnection) -> str:
38
- addrs: tuple[str, str] = ws.remote_address # pyright: ignore[reportAny]
39
- (host, _port) = addrs
40
- return host
41
-
42
-
43
37
  SSL_CERT_PATH: str = environ.get("SSL_CERT_PATH", "./cert.pem")
44
38
  SSL_KEY_PATH: str = environ.get("SSL_KEY_PATH", "./key.pem")
45
39
  PSYNC_HOST: str = environ.get("PSYNC_SERVER_IP", "0.0.0.0")
@@ -88,6 +82,11 @@ class PsyncServer:
88
82
  __coroutine: Task[None] | None = None
89
83
  """The main coroutine for this server."""
90
84
 
85
+ def __get_host(self, ws: ServerConnection) -> str:
86
+ addrs: tuple[str, str] = ws.remote_address # pyright: ignore[reportAny]
87
+ (host, _port) = addrs
88
+ return host
89
+
91
90
  async def serve(self) -> None:
92
91
  """
93
92
  The main interface for the server. Will serve forever, or until exited with SIGINT/Ctrl-C.
@@ -124,7 +123,7 @@ class PsyncServer:
124
123
  return inner
125
124
 
126
125
  async def __end_session(self, ws: ServerConnection):
127
- host = __get_host(ws)
126
+ host = self.__get_host(ws)
128
127
  try:
129
128
  _ = self.__sessions.pop(host)
130
129
  except Exception:
@@ -179,7 +178,7 @@ class PsyncServer:
179
178
  return inner
180
179
 
181
180
  async def __open(self, req: OpenReq, ws: ServerConnection):
182
- host = __get_host(ws)
181
+ host = self.__get_host(ws)
183
182
  if self.__sessions.get(host) is not None:
184
183
  self.__sessions[host]
185
184
  resp = ErrorResp(msg="Process already open for this client.")
@@ -228,7 +227,7 @@ class PsyncServer:
228
227
  pass
229
228
 
230
229
  async def __kill(self, _req: KillReq, ws: ServerConnection):
231
- host = __get_host(ws)
230
+ host = self.__get_host(ws)
232
231
  p = self.__sessions.get(host)
233
232
  task = self.__tasks.get(host)
234
233
  if p is not None and task is not None: