MediaWikiServerTools 0.2.1__tar.gz → 0.2.6__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 (34) hide show
  1. {mediawikiservertools-0.2.1 → mediawikiservertools-0.2.6}/PKG-INFO +2 -1
  2. mediawikiservertools-0.2.6/mwstools_backend/__init__.py +1 -0
  3. {mediawikiservertools-0.2.1 → mediawikiservertools-0.2.6}/mwstools_backend/remote.py +22 -2
  4. {mediawikiservertools-0.2.1 → mediawikiservertools-0.2.6}/mwstools_backend/tsite.py +27 -14
  5. {mediawikiservertools-0.2.1 → mediawikiservertools-0.2.6}/mwstools_backend/version.py +1 -1
  6. {mediawikiservertools-0.2.1 → mediawikiservertools-0.2.6}/pyproject.toml +3 -0
  7. mediawikiservertools-0.2.1/mwstools_backend/__init__.py +0 -1
  8. {mediawikiservertools-0.2.1 → mediawikiservertools-0.2.6}/.github/workflows/build.yml +0 -0
  9. {mediawikiservertools-0.2.1 → mediawikiservertools-0.2.6}/.github/workflows/upload-to-pypi.yml +0 -0
  10. {mediawikiservertools-0.2.1 → mediawikiservertools-0.2.6}/.gitignore +0 -0
  11. {mediawikiservertools-0.2.1 → mediawikiservertools-0.2.6}/.project +0 -0
  12. {mediawikiservertools-0.2.1 → mediawikiservertools-0.2.6}/.pydevproject +0 -0
  13. {mediawikiservertools-0.2.1 → mediawikiservertools-0.2.6}/AGENTS.md +0 -0
  14. {mediawikiservertools-0.2.1 → mediawikiservertools-0.2.6}/LICENSE +0 -0
  15. {mediawikiservertools-0.2.1 → mediawikiservertools-0.2.6}/README.md +0 -0
  16. {mediawikiservertools-0.2.1 → mediawikiservertools-0.2.6}/mwstools_backend/cron_backup.py +0 -0
  17. {mediawikiservertools-0.2.1 → mediawikiservertools-0.2.6}/mwstools_backend/html_table.py +0 -0
  18. {mediawikiservertools-0.2.1 → mediawikiservertools-0.2.6}/mwstools_backend/server.py +0 -0
  19. {mediawikiservertools-0.2.1 → mediawikiservertools-0.2.6}/mwstools_backend/site.py +0 -0
  20. {mediawikiservertools-0.2.1 → mediawikiservertools-0.2.6}/mwstools_backend/sql_backup.py +0 -0
  21. {mediawikiservertools-0.2.1 → mediawikiservertools-0.2.6}/mwstools_backend/webscrape.py +0 -0
  22. {mediawikiservertools-0.2.1 → mediawikiservertools-0.2.6}/mwstools_backend/wikibackup.py +0 -0
  23. {mediawikiservertools-0.2.1 → mediawikiservertools-0.2.6}/scripts/blackisort +0 -0
  24. {mediawikiservertools-0.2.1 → mediawikiservertools-0.2.6}/scripts/doc +0 -0
  25. {mediawikiservertools-0.2.1 → mediawikiservertools-0.2.6}/scripts/install +0 -0
  26. {mediawikiservertools-0.2.1 → mediawikiservertools-0.2.6}/scripts/release +0 -0
  27. {mediawikiservertools-0.2.1 → mediawikiservertools-0.2.6}/scripts/test +0 -0
  28. {mediawikiservertools-0.2.1 → mediawikiservertools-0.2.6}/tests/__init__.py +0 -0
  29. {mediawikiservertools-0.2.1 → mediawikiservertools-0.2.6}/tests/smw_access.py +0 -0
  30. {mediawikiservertools-0.2.1 → mediawikiservertools-0.2.6}/tests/test_remote.py +0 -0
  31. {mediawikiservertools-0.2.1 → mediawikiservertools-0.2.6}/tests/test_server.py +0 -0
  32. {mediawikiservertools-0.2.1 → mediawikiservertools-0.2.6}/tests/test_site.py +0 -0
  33. {mediawikiservertools-0.2.1 → mediawikiservertools-0.2.6}/tests/test_sqlbackup.py +0 -0
  34. {mediawikiservertools-0.2.1 → mediawikiservertools-0.2.6}/tests/test_wikibackup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: MediaWikiServerTools
3
- Version: 0.2.1
3
+ Version: 0.2.6
4
4
  Summary: MediaWikiServerTools: MediaWiki Server Management System
5
5
  Project-URL: Home, https://github.com/BITPlan/MediaWikiServerTools
6
6
  Project-URL: Source, https://github.com/BITPlan/MediaWikiServerTools
@@ -22,6 +22,7 @@ Requires-Dist: beautifulsoup4>=4.9.3
22
22
  Requires-Dist: lxml
23
23
  Requires-Dist: py-3rdparty-mediawiki>=0.19.4
24
24
  Requires-Dist: pybasemkit>=0.2.4
25
+ Requires-Dist: pyexpirebackups>=0.1.3
25
26
  Requires-Dist: pymogwai>=0.1.1
26
27
  Requires-Dist: pymysql>=1.1.1
27
28
  Provides-Extra: test
@@ -0,0 +1 @@
1
+ __version__ = "0.2.6"
@@ -547,11 +547,24 @@ class Remote:
547
547
  self.log.log("✅", "sync", f"{marker_path} already exists")
548
548
  return subprocess.CompletedProcess([], 0, "", "")
549
549
  proc = self.prepare_target_directory(target_path, run_config)
550
+ if proc.returncode == 0 and run_config.should_set_permissions:
551
+ # make the existing target tree group-writable BEFORE rsync so the
552
+ # rsync receiver (running as a www-data group member) can create its
553
+ # temp files in pre-existing images/* subdirs (closes #9).
554
+ # g+rwX adds execute only on directories, leaving files non-executable.
555
+ target_on_host = self.get_path_on_target(target_path)
556
+ if self.get_file_stats(target_on_host) is not None:
557
+ pre_perm_cmds = {
558
+ "chown_tree": f"sudo chown -R {run_config.uid}:{run_config.gid} {target_path}",
559
+ "chmod_tree": f"sudo chmod -R g+rwX {target_path}",
560
+ }
561
+ proc = self.run_cmds_as_single_cmd(pre_perm_cmds)
550
562
  if proc.returncode == 0:
551
563
  timeout = run_config.timeout if run_config else 30
552
564
  rsync_cmd = (
553
565
  f"rsync -avz --no-perms --omit-dir-times --timeout={timeout} {source_path}/* {target_path}"
554
566
  )
567
+ print(f"⚙️ {rsync_cmd}")
555
568
  proc = self.run(rsync_cmd, run_config=run_config)
556
569
 
557
570
  if run_config.should_set_permissions and proc.returncode == 0:
@@ -564,8 +577,15 @@ class Remote:
564
577
  if proc.returncode == 0:
565
578
  self.run(f"touch {marker_path}")
566
579
 
567
- status = "✅" if proc.returncode == 0 else "❌"
568
- self.log.log(status, "sync", f"synching {message}")
580
+ success = proc.returncode == 0
581
+ status = "" if success else "❌"
582
+ message = f"synching {message}"
583
+ if not success:
584
+ # surface the real rsync error instead of swallowing it (closes #8)
585
+ message += (
586
+ f" failed (rc={proc.returncode})\n{proc.stdout}\n{proc.stderr}"
587
+ )
588
+ self.log.log(status, "sync", message)
569
589
 
570
590
  return proc
571
591
 
@@ -5,6 +5,8 @@ Tools to transfer a mediawiki site from one server to another
5
5
  to e.g. migrate the LAMP stack elements or move from a farm based
6
6
  to a dockerized environment
7
7
 
8
+ see also https://www.semantic-mediawiki.org/wiki/SMWCon_Fall_2020/Mediawiki_1.35_Migration
9
+
8
10
  @author: wf
9
11
  """
10
12
 
@@ -89,16 +91,14 @@ class TransferTask:
89
91
  def login(self):
90
92
  """
91
93
  login to the source wiki
94
+
95
+ use WikiClient.login() which goes through the legacy action=login API.
96
+ This works reliably across MediaWiki versions (e.g. 1.35.5) for both
97
+ bot and regular users, whereas site.clientlogin() fails with
98
+ "Incorrect username or password entered" on some wikis (see issue #5).
92
99
  """
93
- wu = self.wikiUser
94
- # bot login
95
- if "@" in wu.user:
96
- self.wikiClient.login()
97
- else:
98
- # just fake a compatible version to allow client login
99
- self.site.version = (1, 35, 5)
100
- self.site.clientlogin(username=wu.user, password=wu.get_password())
101
- pass
100
+ if not self.wikiClient.login():
101
+ raise Exception(f"login to {self.wikiUser.wikiId} failed")
102
102
 
103
103
  def git_target(self, target_path: str) -> subprocess.CompletedProcess:
104
104
  """
@@ -200,6 +200,7 @@ class TransferTask:
200
200
  uid=33, # www-data
201
201
  gid=33, # www-data
202
202
  )
203
+ rsync_prof = Profiler("rsync sync", profile=self.args.profile)
203
204
  proc = self.target.remote.rsync(
204
205
  source_path=source_path,
205
206
  target_path=site_path,
@@ -207,13 +208,20 @@ class TransferTask:
207
208
  message=f"{self.wiki_site.hostname}",
208
209
  run_config=run_config,
209
210
  )
210
- if proc.returncode == 0:
211
- print("✅ sync done")
212
- result = True
211
+ if proc.returncode != 0:
212
+ # abort on rsync failure - do not proceed to git (closes #8)
213
+ print(
214
+ f"❌ rsync sync {self.wiki_site.hostname} failed"
215
+ f" (rc={proc.returncode})\n{proc.stdout}\n{proc.stderr}"
216
+ )
217
+ return False
218
+ rsync_prof.time(f" {self.wiki_site.hostname}")
219
+ result = True
213
220
  if self.use_git:
221
+ git_prof = Profiler("git commit", profile=self.args.profile)
214
222
  proc = self.git_target(target_path=site_path)
215
223
  if proc.returncode == 0:
216
- print(" git committed")
224
+ git_prof.time(f" {self.wiki_site.hostname}")
217
225
  else:
218
226
  result = False
219
227
  return result
@@ -304,7 +312,12 @@ class TransferTask:
304
312
  restore_cmd = (
305
313
  f"pv {self.target_backup_path} | {mysqlr} -D {database}"
306
314
  )
307
- proc = self.target.remote.run(restore_cmd)
315
+ # honor the user supplied --timeout for the (potentially long)
316
+ # SQL restore instead of the 10s RunConfig default (closes #6)
317
+ restore_run_config = RunConfig(timeout=self.timeout)
318
+ proc = self.target.remote.run(
319
+ restore_cmd, run_config=restore_run_config
320
+ )
308
321
  success = proc.returncode == 0
309
322
  result = result and success
310
323
  if success:
@@ -18,7 +18,7 @@ class Version(object):
18
18
  description = "MediaWiki Server Management System - Apache Site management, SQL backups, cron-based backups "
19
19
  version = mwstools_backend.__version__
20
20
  date = "2022-11-16"
21
- updated = "2026-06-05"
21
+ updated = "2026-06-10"
22
22
  authors = "Wolfgang Fahl"
23
23
  doc_url = "https://wiki.bitplan.com/index.php/MediaWikiServerTools"
24
24
  chat_url = "https://github.com/WolfgangFahl/MediaWikiServerTools/discussions"
@@ -30,6 +30,9 @@ dependencies = [
30
30
  'PyMySQL>=1.1.1',
31
31
  # https://pypi.org/project/pyMogwai/
32
32
  "pyMogwai>=0.1.1",
33
+ # https://pypi.org/project/pyExpireBackups/
34
+ # provides the `expirebackups` module imported by mwstools_backend.cron_backup (issue #10)
35
+ "pyExpireBackups>=0.1.3",
33
36
  ]
34
37
 
35
38
  requires-python = ">=3.10"
@@ -1 +0,0 @@
1
- __version__ = "0.2.1"