From 4f7a5629be809381cd9fca7b9dedc041934c244f Mon Sep 17 00:00:00 2001 From: Artyom Semyonov Date: Tue, 26 May 2020 16:34:11 +0300 Subject: [PATCH 01/16] Added enable_glob option --- mackup/appsdb.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/mackup/appsdb.py b/mackup/appsdb.py index 638ff40f4..ae4087a09 100644 --- a/mackup/appsdb.py +++ b/mackup/appsdb.py @@ -4,6 +4,7 @@ The Applications Database provides an easy to use interface to load application data from the Mackup Database (files). """ +import glob import os try: @@ -52,7 +53,7 @@ def __init__(self): raise ValueError( "Unsupported absolute path: {}".format(path) ) - self.apps[app_name]["configuration_files"].add(path) + self._add_path(app_name, path, config) # Add the XDG configuration files to sync home = os.path.expanduser("~/") @@ -72,7 +73,7 @@ def __init__(self): ) path = os.path.join(xdg_config_home, path) path = path.replace(home, "") - (self.apps[app_name]["configuration_files"].add(path)) + self._add_path(app_name, path, config) @staticmethod def get_config_files(): @@ -168,3 +169,12 @@ def get_pretty_app_names(self): pretty_app_names.add(self.get_name(app_name)) return pretty_app_names + + def _add_path(self, app_name, path, config): + if config.getboolean('options', 'enable_glob', fallback=False): + expanded_paths = glob.glob(path) + else: + expanded_paths = [path] + for expanded_path in expanded_paths: + self.apps[app_name]["configuration_files"].add(expanded_path) + From 00bc4007e5ec2c62622f8337b1ddd0957ac787ed Mon Sep 17 00:00:00 2001 From: Artyom Semyonov Date: Tue, 26 May 2020 16:34:34 +0300 Subject: [PATCH 02/16] Added traktor application as example that using enable_glob option --- mackup/applications/traktor.cfg | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 mackup/applications/traktor.cfg diff --git a/mackup/applications/traktor.cfg b/mackup/applications/traktor.cfg new file mode 100644 index 000000000..1ef1bedd1 --- /dev/null +++ b/mackup/applications/traktor.cfg @@ -0,0 +1,8 @@ +[application] +name = Traktor + +[options] +enable_glob = true + +[configuration_files] +Documents/Native Instruments/Traktor *.*.*/Traktor Settings.tsi From fd91ef98fe18f285c73faa4ce819d692748638b5 Mon Sep 17 00:00:00 2001 From: Artyom Semyonov Date: Tue, 26 May 2020 16:54:05 +0300 Subject: [PATCH 03/16] enable_glob: fixed formatting --- mackup/appsdb.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mackup/appsdb.py b/mackup/appsdb.py index ae4087a09..5d1978aa0 100644 --- a/mackup/appsdb.py +++ b/mackup/appsdb.py @@ -171,10 +171,9 @@ def get_pretty_app_names(self): return pretty_app_names def _add_path(self, app_name, path, config): - if config.getboolean('options', 'enable_glob', fallback=False): + if config.getboolean("options", "enable_glob", fallback=False): expanded_paths = glob.glob(path) else: expanded_paths = [path] for expanded_path in expanded_paths: self.apps[app_name]["configuration_files"].add(expanded_path) - From 5c490d9da6fc8be4ea0b651bb1f00f0fd324fc6a Mon Sep 17 00:00:00 2001 From: Jim Neuendorf Date: Tue, 15 Mar 2022 00:00:07 +0100 Subject: [PATCH 04/16] enable glob patterns for configuration files, tests --- Makefile | 2 +- Pipfile | 3 +- Pipfile.lock | 284 +++++++++++------- mackup/appsdb.py | 30 +- mackup/config.py | 2 +- tests/README.md | 5 +- tests/apps_config_tests.py | 57 ++++ tests/config_tests.py | 60 ++-- .../Test App/2020/data.txt | 1 + .../Test App/2021/data.txt | 1 + .../Test App/2022/data.txt | 1 + 11 files changed, 289 insertions(+), 157 deletions(-) create mode 100644 tests/apps_config_tests.py create mode 100644 tests/fixtures/Library/Application Support/Test App/2020/data.txt create mode 100644 tests/fixtures/Library/Application Support/Test App/2021/data.txt create mode 100644 tests/fixtures/Library/Application Support/Test App/2022/data.txt diff --git a/Makefile b/Makefile index 1a6c23485..2098f4cf7 100644 --- a/Makefile +++ b/Makefile @@ -20,4 +20,4 @@ release: clean pipenv run twine upload dist/* black: - black --target-version py27 . + pipenv run black --target-version py34 . diff --git a/Pipfile b/Pipfile index 000429f63..1ee1d93a1 100644 --- a/Pipfile +++ b/Pipfile @@ -8,8 +8,7 @@ docopt = "*" six = "*" [dev-packages] -# Black is still a pre-release. Replaced with `brew install black` for now. -# black = "*" +black = "*" coverage = "*" nose = "*" twine = "*" diff --git a/Pipfile.lock b/Pipfile.lock index e5ac1744c..d813adda0 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "b7c480e641440c1617f3beb17e1085abc0bcbbaa937da6f7ffe8fa50f2eeb2b1" + "sha256": "f0033694fee8af976ee2ccbbf9ff782a07e600ff9e3908fe1ede5a41f118af67" }, "pipfile-spec": 6, "requires": {}, @@ -31,6 +31,35 @@ } }, "develop": { + "black": { + "hashes": [ + "sha256:07e5c049442d7ca1a2fc273c79d1aecbbf1bc858f62e8184abe1ad175c4f7cc2", + "sha256:0e21e1f1efa65a50e3960edd068b6ae6d64ad6235bd8bfea116a03b21836af71", + "sha256:1297c63b9e1b96a3d0da2d85d11cd9bf8664251fd69ddac068b98dc4f34f73b6", + "sha256:228b5ae2c8e3d6227e4bde5920d2fc66cc3400fde7bcc74f480cb07ef0b570d5", + "sha256:2d6f331c02f0f40aa51a22e479c8209d37fcd520c77721c034517d44eecf5912", + "sha256:2ff96450d3ad9ea499fc4c60e425a1439c2120cbbc1ab959ff20f7c76ec7e866", + "sha256:3524739d76b6b3ed1132422bf9d82123cd1705086723bc3e235ca39fd21c667d", + "sha256:35944b7100af4a985abfcaa860b06af15590deb1f392f06c8683b4381e8eeaf0", + "sha256:373922fc66676133ddc3e754e4509196a8c392fec3f5ca4486673e685a421321", + "sha256:5fa1db02410b1924b6749c245ab38d30621564e658297484952f3d8a39fce7e8", + "sha256:6f2f01381f91c1efb1451998bd65a129b3ed6f64f79663a55fe0e9b74a5f81fd", + "sha256:742ce9af3086e5bd07e58c8feb09dbb2b047b7f566eb5f5bc63fd455814979f3", + "sha256:7835fee5238fc0a0baf6c9268fb816b5f5cd9b8793423a75e8cd663c48d073ba", + "sha256:8871fcb4b447206904932b54b567923e5be802b9b19b744fdff092bd2f3118d0", + "sha256:a7c0192d35635f6fc1174be575cb7915e92e5dd629ee79fdaf0dcfa41a80afb5", + "sha256:b1a5ed73ab4c482208d20434f700d514f66ffe2840f63a6252ecc43a9bc77e8a", + "sha256:c8226f50b8c34a14608b848dc23a46e5d08397d009446353dad45e04af0c8e28", + "sha256:ccad888050f5393f0d6029deea2a33e5ae371fd182a697313bdbd835d3edaf9c", + "sha256:dae63f2dbf82882fa3b2a3c49c32bffe144970a573cd68d247af6560fc493ae1", + "sha256:e2f69158a7d120fd641d1fa9a921d898e20d52e44a74a6fbbcc570a62a6bc8ab", + "sha256:efbadd9b52c060a8fc3b9658744091cb33c31f830b3f074422ed27bad2b18e8f", + "sha256:f5660feab44c2e3cb24b2419b998846cbb01c23c7fe645fee45087efa3da2d61", + "sha256:fdb8754b453fb15fad3f72cd9cad3e16776f0964d67cf30ebcbf10327a3777a3" + ], + "index": "pypi", + "version": "==22.1.0" + }, "bleach": { "hashes": [ "sha256:0900d8b37eba61a802ee40ac0061f8c2b5dee29c1927dd1d233e075ebf5a71da", @@ -41,18 +70,26 @@ }, "certifi": { "hashes": [ - "sha256:2bbf76fd432960138b3ef6dda3dde0544f27cbf8546c458e60baf371917ba9ee", - "sha256:50b1e4f8446b06f41be7dd6338db18e0990601dce795c2b1686458aa7e8fa7d8" + "sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872", + "sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569" ], - "version": "==2021.5.30" + "version": "==2021.10.8" }, "charset-normalizer": { "hashes": [ - "sha256:0c8911edd15d19223366a194a513099a302055a962bca2cec0f54b8b63175d8b", - "sha256:f23667ebe1084be45f6ae0538e4a5a865206544097e4e8bbcacf42cd02a348f3" + "sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597", + "sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df" ], "markers": "python_version >= '3'", - "version": "==2.0.4" + "version": "==2.0.12" + }, + "click": { + "hashes": [ + "sha256:6a7a62563bbfabfda3a38f3023a1db4a35978c0abd76f6c9605ecd6554d6d9b1", + "sha256:8458d7b1287c5fb128c90e23381cf99dcde74beaf6c7ff6384ce84d6fe090adb" + ], + "markers": "python_version >= '3.6'", + "version": "==8.0.4" }, "colorama": { "hashes": [ @@ -64,93 +101,89 @@ }, "coverage": { "hashes": [ - "sha256:004d1880bed2d97151facef49f08e255a20ceb6f9432df75f4eef018fdd5a78c", - "sha256:01d84219b5cdbfc8122223b39a954820929497a1cb1422824bb86b07b74594b6", - "sha256:040af6c32813fa3eae5305d53f18875bedd079960822ef8ec067a66dd8afcd45", - "sha256:06191eb60f8d8a5bc046f3799f8a07a2d7aefb9504b0209aff0b47298333302a", - "sha256:13034c4409db851670bc9acd836243aeee299949bd5673e11844befcb0149f03", - "sha256:13c4ee887eca0f4c5a247b75398d4114c37882658300e153113dafb1d76de529", - "sha256:184a47bbe0aa6400ed2d41d8e9ed868b8205046518c52464fde713ea06e3a74a", - "sha256:18ba8bbede96a2c3dde7b868de9dcbd55670690af0988713f0603f037848418a", - "sha256:1aa846f56c3d49205c952d8318e76ccc2ae23303351d9270ab220004c580cfe2", - "sha256:217658ec7187497e3f3ebd901afdca1af062b42cfe3e0dafea4cced3983739f6", - "sha256:24d4a7de75446be83244eabbff746d66b9240ae020ced65d060815fac3423759", - "sha256:2910f4d36a6a9b4214bb7038d537f015346f413a975d57ca6b43bf23d6563b53", - "sha256:2949cad1c5208b8298d5686d5a85b66aae46d73eec2c3e08c817dd3513e5848a", - "sha256:2a3859cb82dcbda1cfd3e6f71c27081d18aa251d20a17d87d26d4cd216fb0af4", - "sha256:2cafbbb3af0733db200c9b5f798d18953b1a304d3f86a938367de1567f4b5bff", - "sha256:2e0d881ad471768bf6e6c2bf905d183543f10098e3b3640fc029509530091502", - "sha256:30c77c1dc9f253283e34c27935fded5015f7d1abe83bc7821680ac444eaf7793", - "sha256:3487286bc29a5aa4b93a072e9592f22254291ce96a9fbc5251f566b6b7343cdb", - "sha256:372da284cfd642d8e08ef606917846fa2ee350f64994bebfbd3afb0040436905", - "sha256:41179b8a845742d1eb60449bdb2992196e211341818565abded11cfa90efb821", - "sha256:44d654437b8ddd9eee7d1eaee28b7219bec228520ff809af170488fd2fed3e2b", - "sha256:4a7697d8cb0f27399b0e393c0b90f0f1e40c82023ea4d45d22bce7032a5d7b81", - "sha256:51cb9476a3987c8967ebab3f0fe144819781fca264f57f89760037a2ea191cb0", - "sha256:52596d3d0e8bdf3af43db3e9ba8dcdaac724ba7b5ca3f6358529d56f7a166f8b", - "sha256:53194af30d5bad77fcba80e23a1441c71abfb3e01192034f8246e0d8f99528f3", - "sha256:5fec2d43a2cc6965edc0bb9e83e1e4b557f76f843a77a2496cbe719583ce8184", - "sha256:6c90e11318f0d3c436a42409f2749ee1a115cd8b067d7f14c148f1ce5574d701", - "sha256:74d881fc777ebb11c63736622b60cb9e4aee5cace591ce274fb69e582a12a61a", - "sha256:7501140f755b725495941b43347ba8a2777407fc7f250d4f5a7d2a1050ba8e82", - "sha256:796c9c3c79747146ebd278dbe1e5c5c05dd6b10cc3bcb8389dfdf844f3ead638", - "sha256:869a64f53488f40fa5b5b9dcb9e9b2962a66a87dab37790f3fcfb5144b996ef5", - "sha256:8963a499849a1fc54b35b1c9f162f4108017b2e6db2c46c1bed93a72262ed083", - "sha256:8d0a0725ad7c1a0bcd8d1b437e191107d457e2ec1084b9f190630a4fb1af78e6", - "sha256:900fbf7759501bc7807fd6638c947d7a831fc9fdf742dc10f02956ff7220fa90", - "sha256:92b017ce34b68a7d67bd6d117e6d443a9bf63a2ecf8567bb3d8c6c7bc5014465", - "sha256:970284a88b99673ccb2e4e334cfb38a10aab7cd44f7457564d11898a74b62d0a", - "sha256:972c85d205b51e30e59525694670de6a8a89691186012535f9d7dbaa230e42c3", - "sha256:9a1ef3b66e38ef8618ce5fdc7bea3d9f45f3624e2a66295eea5e57966c85909e", - "sha256:af0e781009aaf59e25c5a678122391cb0f345ac0ec272c7961dc5455e1c40066", - "sha256:b6d534e4b2ab35c9f93f46229363e17f63c53ad01330df9f2d6bd1187e5eaacf", - "sha256:b7895207b4c843c76a25ab8c1e866261bcfe27bfaa20c192de5190121770672b", - "sha256:c0891a6a97b09c1f3e073a890514d5012eb256845c451bd48f7968ef939bf4ae", - "sha256:c2723d347ab06e7ddad1a58b2a821218239249a9e4365eaff6649d31180c1669", - "sha256:d1f8bf7b90ba55699b3a5e44930e93ff0189aa27186e96071fac7dd0d06a1873", - "sha256:d1f9ce122f83b2305592c11d64f181b87153fc2c2bbd3bb4a3dde8303cfb1a6b", - "sha256:d314ed732c25d29775e84a960c3c60808b682c08d86602ec2c3008e1202e3bb6", - "sha256:d636598c8305e1f90b439dbf4f66437de4a5e3c31fdf47ad29542478c8508bbb", - "sha256:deee1077aae10d8fa88cb02c845cfba9b62c55e1183f52f6ae6a2df6a2187160", - "sha256:ebe78fe9a0e874362175b02371bdfbee64d8edc42a044253ddf4ee7d3c15212c", - "sha256:f030f8873312a16414c0d8e1a1ddff2d3235655a2174e3648b4fa66b3f2f1079", - "sha256:f0b278ce10936db1a37e6954e15a3730bea96a0997c26d7fee88e6c396c2086d", - "sha256:f11642dddbb0253cc8853254301b51390ba0081750a8ac03f20ea8103f0c56b6" + "sha256:03e2a7826086b91ef345ff18742ee9fc47a6839ccd517061ef8fa1976e652ce9", + "sha256:07e6db90cd9686c767dcc593dff16c8c09f9814f5e9c51034066cad3373b914d", + "sha256:18d520c6860515a771708937d2f78f63cc47ab3b80cb78e86573b0a760161faf", + "sha256:1ebf730d2381158ecf3dfd4453fbca0613e16eaa547b4170e2450c9707665ce7", + "sha256:21b7745788866028adeb1e0eca3bf1101109e2dc58456cb49d2d9b99a8c516e6", + "sha256:26e2deacd414fc2f97dd9f7676ee3eaecd299ca751412d89f40bc01557a6b1b4", + "sha256:2c6dbb42f3ad25760010c45191e9757e7dce981cbfb90e42feef301d71540059", + "sha256:2fea046bfb455510e05be95e879f0e768d45c10c11509e20e06d8fcaa31d9e39", + "sha256:34626a7eee2a3da12af0507780bb51eb52dca0e1751fd1471d0810539cefb536", + "sha256:37d1141ad6b2466a7b53a22e08fe76994c2d35a5b6b469590424a9953155afac", + "sha256:46191097ebc381fbf89bdce207a6c107ac4ec0890d8d20f3360345ff5976155c", + "sha256:4dd8bafa458b5c7d061540f1ee9f18025a68e2d8471b3e858a9dad47c8d41903", + "sha256:4e21876082ed887baed0146fe222f861b5815455ada3b33b890f4105d806128d", + "sha256:58303469e9a272b4abdb9e302a780072c0633cdcc0165db7eec0f9e32f901e05", + "sha256:5ca5aeb4344b30d0bec47481536b8ba1181d50dbe783b0e4ad03c95dc1296684", + "sha256:68353fe7cdf91f109fc7d474461b46e7f1f14e533e911a2a2cbb8b0fc8613cf1", + "sha256:6f89d05e028d274ce4fa1a86887b071ae1755082ef94a6740238cd7a8178804f", + "sha256:7a15dc0a14008f1da3d1ebd44bdda3e357dbabdf5a0b5034d38fcde0b5c234b7", + "sha256:8bdde1177f2311ee552f47ae6e5aa7750c0e3291ca6b75f71f7ffe1f1dab3dca", + "sha256:8ce257cac556cb03be4a248d92ed36904a59a4a5ff55a994e92214cde15c5bad", + "sha256:8cf5cfcb1521dc3255d845d9dca3ff204b3229401994ef8d1984b32746bb45ca", + "sha256:8fbbdc8d55990eac1b0919ca69eb5a988a802b854488c34b8f37f3e2025fa90d", + "sha256:9548f10d8be799551eb3a9c74bbf2b4934ddb330e08a73320123c07f95cc2d92", + "sha256:96f8a1cb43ca1422f36492bebe63312d396491a9165ed3b9231e778d43a7fca4", + "sha256:9b27d894748475fa858f9597c0ee1d4829f44683f3813633aaf94b19cb5453cf", + "sha256:9baff2a45ae1f17c8078452e9e5962e518eab705e50a0aa8083733ea7d45f3a6", + "sha256:a2a8b8bcc399edb4347a5ca8b9b87e7524c0967b335fbb08a83c8421489ddee1", + "sha256:acf53bc2cf7282ab9b8ba346746afe703474004d9e566ad164c91a7a59f188a4", + "sha256:b0be84e5a6209858a1d3e8d1806c46214e867ce1b0fd32e4ea03f4bd8b2e3359", + "sha256:b31651d018b23ec463e95cf10070d0b2c548aa950a03d0b559eaa11c7e5a6fa3", + "sha256:b78e5afb39941572209f71866aa0b206c12f0109835aa0d601e41552f9b3e620", + "sha256:c76aeef1b95aff3905fb2ae2d96e319caca5b76fa41d3470b19d4e4a3a313512", + "sha256:dd035edafefee4d573140a76fdc785dc38829fe5a455c4bb12bac8c20cfc3d69", + "sha256:dd6fe30bd519694b356cbfcaca9bd5c1737cddd20778c6a581ae20dc8c04def2", + "sha256:e5f4e1edcf57ce94e5475fe09e5afa3e3145081318e5fd1a43a6b4539a97e518", + "sha256:ec6bc7fe73a938933d4178c9b23c4e0568e43e220aef9472c4f6044bfc6dd0f0", + "sha256:f1555ea6d6da108e1999b2463ea1003fe03f29213e459145e70edbaf3e004aaa", + "sha256:f5fa5803f47e095d7ad8443d28b01d48c0359484fec1b9d8606d0e3282084bc4", + "sha256:f7331dbf301b7289013175087636bbaf5b2405e57259dd2c42fdcc9fcc47325e", + "sha256:f9987b0354b06d4df0f4d3e0ec1ae76d7ce7cbca9a2f98c25041eb79eec766f1", + "sha256:fd9e830e9d8d89b20ab1e5af09b32d33e1a08ef4c4e14411e559556fd788e6b2" ], "index": "pypi", - "version": "==5.5" + "version": "==6.3.2" }, "docutils": { "hashes": [ - "sha256:686577d2e4c32380bb50cbb22f575ed742d58168cee37e99117a854bcd88f125", - "sha256:cf316c8370a737a022b72b56874f6602acf974a37a9fba42ec2876387549fc61" + "sha256:23010f129180089fbcd3bc08cfefccb3b890b0050e1ca00c867036e9d161b98c", + "sha256:679987caf361a7539d76e584cbeddc311e3aee937877c87346f31debc63e9d06" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==0.17.1" + "version": "==0.18.1" }, "idna": { "hashes": [ - "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a", - "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3" + "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff", + "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d" ], "markers": "python_version >= '3'", - "version": "==3.2" + "version": "==3.3" }, "importlib-metadata": { "hashes": [ - "sha256:b618b6d2d5ffa2f16add5697cf57a46c76a56229b0ed1c438322e4e95645bd15", - "sha256:f284b3e11256ad1e5d03ab86bb2ccd6f5339688ff17a4d797a0fe7df326f23b1" + "sha256:1208431ca90a8cca1a6b8af391bb53c1a2db74e5d1cef6ddced95d4b2062edc6", + "sha256:ea4c597ebf37142f827b8f39299579e31685c31d3a438b59f469406afd0f2539" ], - "markers": "python_version >= '3.6'", - "version": "==4.8.1" + "markers": "python_version >= '3.7'", + "version": "==4.11.3" }, "keyring": { "hashes": [ - "sha256:b32397fd7e7063f8dd74a26db910c9862fc2109285fa16e3b5208bcb42a3e579", - "sha256:b7e0156667f5dcc73c1f63a518005cd18a4eb23fe77321194fefcc03748b21a4" + "sha256:9012508e141a80bd1c0b6778d5c610dd9f8c464d75ac6774248500503f972fb9", + "sha256:b0d28928ac3ec8e42ef4cc227822647a19f1d544f21f96457965dc01cf555261" ], - "markers": "python_version >= '3.6'", - "version": "==23.1.0" + "markers": "python_version >= '3.7'", + "version": "==23.5.0" + }, + "mypy-extensions": { + "hashes": [ + "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d", + "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8" + ], + "version": "==0.4.3" }, "nose": { "hashes": [ @@ -163,49 +196,65 @@ }, "packaging": { "hashes": [ - "sha256:7dc96269f53a4ccec5c0670940a4281106dd0bb343f47b7471f779df49c2fbe7", - "sha256:c86254f9220d55e31cc94d69bade760f0847da8000def4dfe1c6b872fd14ff14" + "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb", + "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522" ], "markers": "python_version >= '3.6'", - "version": "==21.0" + "version": "==21.3" + }, + "pathspec": { + "hashes": [ + "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a", + "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1" + ], + "version": "==0.9.0" }, "pkginfo": { "hashes": [ - "sha256:37ecd857b47e5f55949c41ed061eb51a0bee97a87c969219d144c0e023982779", - "sha256:e7432f81d08adec7297633191bbf0bd47faf13cd8724c3a13250e51d542635bd" + "sha256:542e0d0b6750e2e21c20179803e40ab50598d8066d51097a0e382cba9eb02bff", + "sha256:c24c487c6a7f72c66e816ab1796b96ac6c3d14d49338293d2141664330b55ffc" ], - "version": "==1.7.1" + "version": "==1.8.2" + }, + "platformdirs": { + "hashes": [ + "sha256:7535e70dfa32e84d4b34996ea99c5e432fa29a708d0f4e394bbcb2a8faa4f16d", + "sha256:bcae7cab893c2d310a711b70b24efb93334febe65f8de776ee320b517471e227" + ], + "markers": "python_version >= '3.7'", + "version": "==2.5.1" }, "pygments": { "hashes": [ - "sha256:b8e67fe6af78f492b3c4b3e2970c0624cbf08beb1e493b2c99b9fa1b67a20380", - "sha256:f398865f7eb6874156579fdf36bc840a03cab64d1cde9e93d68f46a425ec52c6" + "sha256:44238f1b60a76d78fc8ca0528ee429702aae011c265fe6a8dd8b63049ae41c65", + "sha256:4e426f72023d88d03b2fa258de560726ce890ff3b630f88c21cbb8b2503b8c6a" ], "markers": "python_version >= '3.5'", - "version": "==2.10.0" + "version": "==2.11.2" }, "pyparsing": { "hashes": [ - "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1", - "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b" + "sha256:18ee9022775d270c55187733956460083db60b37d0d0fb357445f3094eed3eea", + "sha256:a6c06a88f252e6c322f65faf8f418b16213b51bdfaece0524c1c1bc30c63c484" ], - "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==2.4.7" + "markers": "python_version >= '3.6'", + "version": "==3.0.7" }, "readme-renderer": { "hashes": [ - "sha256:63b4075c6698fcfa78e584930f07f39e05d46f3ec97f65006e430b595ca6348c", - "sha256:92fd5ac2bf8677f310f3303aa4bce5b9d5f9f2094ab98c29f13791d7b805a3db" + "sha256:262510fe6aae81ed4e94d8b169077f325614c0b1a45916a80442c6576264a9c2", + "sha256:dfb4d17f21706d145f7473e0b61ca245ba58e810cf9b2209a48239677f82e5b0" ], - "version": "==29.0" + "markers": "python_version >= '3.6'", + "version": "==34.0" }, "requests": { "hashes": [ - "sha256:6c1246513ecd5ecd4528a0906f910e8f0f9c6b8ec72030dc9fd154dc1a6efd24", - "sha256:b8aa58f8cf793ffd8782d3d8cb19e66ef36f7aba4353eec859e74678b01b07a7" + "sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61", + "sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", - "version": "==2.26.0" + "version": "==2.27.1" }, "requests-toolbelt": { "hashes": [ @@ -216,10 +265,11 @@ }, "rfc3986": { "hashes": [ - "sha256:270aaf10d87d0d4e095063c65bf3ddbc6ee3d0b226328ce21e036f946e421835", - "sha256:a86d6e1f5b1dc238b218b012df0aa79409667bb209e58da56d0b94704e712a97" + "sha256:50b1502b60e289cb37883f3dfd34532b8873c7de9f49bb546641ce9cbd256ebd", + "sha256:97aacf9dbd4bfd829baad6e6309fa6573aaf1be3f6fa735c8ab05e46cecb261c" ], - "version": "==1.5.0" + "markers": "python_version >= '3.7'", + "version": "==2.0.0" }, "six": { "hashes": [ @@ -229,29 +279,45 @@ "index": "pypi", "version": "==1.16.0" }, + "tomli": { + "hashes": [ + "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc", + "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f" + ], + "markers": "python_version >= '3.7'", + "version": "==2.0.1" + }, "tqdm": { "hashes": [ - "sha256:80aead664e6c1672c4ae20dc50e1cdc5e20eeff9b14aa23ecd426375b28be588", - "sha256:a4d6d112e507ef98513ac119ead1159d286deab17dffedd96921412c2d236ff5" + "sha256:1d9835ede8e394bb8c9dcbffbca02d717217113adc679236873eeaac5bc0b3cd", + "sha256:e643e071046f17139dea55b880dc9b33822ce21613b4a4f5ea57f202833dbc29" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==4.62.2" + "version": "==4.63.0" }, "twine": { "hashes": [ - "sha256:087328e9bb405e7ce18527a2dca4042a84c7918658f951110b38bc135acab218", - "sha256:4caec0f1ed78dc4c9b83ad537e453d03ce485725f2aea57f1bb3fdde78dae936" + "sha256:8efa52658e0ae770686a13b675569328f1fba9837e5de1867bfe5f46a9aefe19", + "sha256:d0550fca9dc19f3d5e8eadfce0c227294df0a2a951251a4385797c8a6198b7c8" ], "index": "pypi", - "version": "==3.4.2" + "version": "==3.8.0" + }, + "typing-extensions": { + "hashes": [ + "sha256:1a9462dcc3347a79b1f1c0271fbe79e844580bb598bafa1ed208b94da3cdcd42", + "sha256:21c85e0fe4b9a155d0799430b0ad741cdce7e359660ccbd8b530613e8df88ce2" + ], + "markers": "python_version < '3.10'", + "version": "==4.1.1" }, "urllib3": { "hashes": [ - "sha256:39fb8672126159acb139a7718dd10806104dec1e2f0f6c88aab05d17df10c8d4", - "sha256:f57b4c16c62fa2760b7e3d97c35b255512fb6b59a259730f36ba32ce9f8e342f" + "sha256:000ca7f471a233c2251c6c7023ee85305721bfdf18621ebff4fd17a8653427ed", + "sha256:0e7c33d9a63e7ddfcb86780aac87befc2fbddf46c58dbb487e0855f7ceec283c" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'", - "version": "==1.26.6" + "version": "==1.26.8" }, "webencodings": { "hashes": [ @@ -262,11 +328,11 @@ }, "zipp": { "hashes": [ - "sha256:957cfda87797e389580cb8b9e3870841ca991e2125350677b2ca83a0e99390a3", - "sha256:f5812b1e007e48cff63449a5e9f4e7ebea716b4111f9c4f9a645f91d579bf0c4" + "sha256:9f50f446828eb9d45b267433fd3e9da8d801f614129124863f9c51ebceafb87d", + "sha256:b47250dd24f92b7dd6a0a8fc5244da14608f3ca90a5efcd37a3b1642fac9a375" ], - "markers": "python_version >= '3.6'", - "version": "==3.5.0" + "markers": "python_version >= '3.7'", + "version": "==3.7.0" } } } diff --git a/mackup/appsdb.py b/mackup/appsdb.py index 5d1978aa0..3b5cae52f 100644 --- a/mackup/appsdb.py +++ b/mackup/appsdb.py @@ -6,6 +6,7 @@ """ import glob import os +from pathlib import Path try: import configparser @@ -35,25 +36,27 @@ def __init__(self): if config.read(config_file): # Get the filename without the directory name filename = os.path.basename(config_file) - # The app name is the cfg filename with the extension + # The app name is the cfg filename without the extension app_name = filename[: -len(".cfg")] # Start building a dict for this app - self.apps[app_name] = dict() + app = dict() # Add the fancy name for the app, for display purpose app_pretty_name = config.get("application", "name") - self.apps[app_name]["name"] = app_pretty_name + app["name"] = app_pretty_name # Add the configuration files to sync - self.apps[app_name]["configuration_files"] = set() + app["configuration_files"] = set() if config.has_section("configuration_files"): for path in config.options("configuration_files"): if path.startswith("/"): raise ValueError( "Unsupported absolute path: {}".format(path) ) - self._add_path(app_name, path, config) + app["configuration_files"] |= self.get_resolves_paths( + path, config + ) # Add the XDG configuration files to sync home = os.path.expanduser("~/") @@ -73,7 +76,11 @@ def __init__(self): ) path = os.path.join(xdg_config_home, path) path = path.replace(home, "") - self._add_path(app_name, path, config) + app["configuration_files"] |= self.get_resolves_paths( + path, config + ) + + self.apps[app_name] = app @staticmethod def get_config_files(): @@ -170,10 +177,11 @@ def get_pretty_app_names(self): return pretty_app_names - def _add_path(self, app_name, path, config): + def get_resolves_paths(self, path, config): if config.getboolean("options", "enable_glob", fallback=False): - expanded_paths = glob.glob(path) + return { + str(p.relative_to(os.environ["HOME"])) + for p in Path(os.environ["HOME"]).glob(path) + } else: - expanded_paths = [path] - for expanded_path in expanded_paths: - self.apps[app_name]["configuration_files"].add(expanded_path) + return set([path]) diff --git a/mackup/config.py b/mackup/config.py index 373bef984..9c67a7dc2 100644 --- a/mackup/config.py +++ b/mackup/config.py @@ -148,7 +148,7 @@ def _setup_parser(self, filename=None): filename = MACKUP_CONFIG_FILE parser = configparser.SafeConfigParser(allow_no_value=True) - parser.read(os.path.join(os.path.join(os.environ["HOME"], filename))) + parser.read(os.path.join(os.environ["HOME"], filename)) return parser diff --git a/tests/README.md b/tests/README.md index a1d04f737..3f24728db 100644 --- a/tests/README.md +++ b/tests/README.md @@ -7,9 +7,8 @@ Feel free to add more, the more the better! ## How to run the tests ```bash -cd src/mackup -pip install -r requirements.txt -nosetests +pipenv install --dev +make test ``` And you should see diff --git a/tests/apps_config_tests.py b/tests/apps_config_tests.py new file mode 100644 index 000000000..4f4ac2b52 --- /dev/null +++ b/tests/apps_config_tests.py @@ -0,0 +1,57 @@ +import os +import tempfile +import unittest +from unittest.mock import patch +import stat + +from mackup import utils +from mackup.appsdb import ApplicationsDatabase + + +realpath = os.path.dirname(os.path.realpath(__file__)) +APPLICATIONS_DIR = os.path.join(realpath, "..", "mackup", "applications") +FIXTURES_DIR = os.path.join(realpath, "fixtures") + + +class TestMackup(unittest.TestCase): + config_file_path = os.path.join(APPLICATIONS_DIR, "test-app.cfg") + + def setUp(self): + os.environ["HOME"] = FIXTURES_DIR + + with open(self.config_file_path, "w") as config_file: + config_file.write( + "\n".join( + [ + "[application]", + "name = Test App", + "", + "[options]", + "enable_glob = true", + "", + "[configuration_files]", + "Library/Application Support/Test App/*/data.txt", + ] + ) + ) + + def tearDown(self): + os.remove(self.config_file_path) + + def test_glob_configuration_paths(self): + with patch.object( + ApplicationsDatabase, + "get_config_files", + return_value=[self.config_file_path], + ) as method: + app_db = ApplicationsDatabase() + print(app_db.apps) + + self.assertEqual( + app_db.get_files("test-app"), + { + "Library/Application Support/Test App/2020/data.txt", + "Library/Application Support/Test App/2021/data.txt", + "Library/Application Support/Test App/2022/data.txt", + }, + ) diff --git a/tests/config_tests.py b/tests/config_tests.py index 6f5bab59d..fa07c8c2c 100644 --- a/tests/config_tests.py +++ b/tests/config_tests.py @@ -28,10 +28,10 @@ def test_config_no_config(self): assert cfg.path == "/home/some_user/Dropbox" assert isinstance(cfg.directory, str) - assert cfg.directory == u"Mackup" + assert cfg.directory == "Mackup" assert isinstance(cfg.fullpath, str) - assert cfg.fullpath == u"/home/some_user/Dropbox/Mackup" + assert cfg.fullpath == "/home/some_user/Dropbox/Mackup" assert cfg.apps_to_ignore == set() assert cfg.apps_to_sync == set() @@ -43,13 +43,13 @@ def test_config_empty(self): assert cfg.engine == ENGINE_DROPBOX assert isinstance(cfg.path, str) - assert cfg.path == u"/home/some_user/Dropbox" + assert cfg.path == "/home/some_user/Dropbox" assert isinstance(cfg.directory, str) - assert cfg.directory == u"Mackup" + assert cfg.directory == "Mackup" assert isinstance(cfg.fullpath, str) - assert cfg.fullpath == u"/home/some_user/Dropbox/Mackup" + assert cfg.fullpath == "/home/some_user/Dropbox/Mackup" assert cfg.apps_to_ignore == set() assert cfg.apps_to_sync == set() @@ -61,13 +61,13 @@ def test_config_engine_dropbox(self): assert cfg.engine == ENGINE_DROPBOX assert isinstance(cfg.path, str) - assert cfg.path == u"/home/some_user/Dropbox" + assert cfg.path == "/home/some_user/Dropbox" assert isinstance(cfg.directory, str) - assert cfg.directory == u"some_weirld_name" + assert cfg.directory == "some_weirld_name" assert isinstance(cfg.fullpath, str) - assert cfg.fullpath == u"/home/some_user/Dropbox/some_weirld_name" + assert cfg.fullpath == "/home/some_user/Dropbox/some_weirld_name" assert cfg.apps_to_ignore == set() assert cfg.apps_to_sync == set() @@ -79,13 +79,13 @@ def test_config_engine_filesystem_absolute(self): assert cfg.engine == ENGINE_FS assert isinstance(cfg.path, str) - assert cfg.path == u"/some/absolute/folder" + assert cfg.path == "/some/absolute/folder" assert isinstance(cfg.directory, str) - assert cfg.directory == u"custom_folder" + assert cfg.directory == "custom_folder" assert isinstance(cfg.fullpath, str) - assert cfg.fullpath == u"/some/absolute/folder/custom_folder" + assert cfg.fullpath == "/some/absolute/folder/custom_folder" assert cfg.apps_to_ignore == set(["subversion", "sequel-pro"]) assert cfg.apps_to_sync == set() @@ -98,15 +98,15 @@ def test_config_engine_filesystem(self): assert isinstance(cfg.path, str) assert cfg.path.endswith( - os.path.join(os.environ[u"HOME"], u"some/relative/folder") + os.path.join(os.environ["HOME"], "some/relative/folder") ) assert isinstance(cfg.directory, str) - assert cfg.directory == u"Mackup" + assert cfg.directory == "Mackup" assert isinstance(cfg.fullpath, str) assert cfg.fullpath == os.path.join( - os.environ[u"HOME"], u"some/relative/folder", u"Mackup" + os.environ["HOME"], "some/relative/folder", "Mackup" ) assert cfg.apps_to_ignore == set() @@ -119,13 +119,13 @@ def test_config_engine_google_drive(self): assert cfg.engine == ENGINE_GDRIVE assert isinstance(cfg.path, str) - assert cfg.path == u"/Users/whatever/Google Drive" + assert cfg.path == "/Users/whatever/Google Drive" assert isinstance(cfg.directory, str) - assert cfg.directory == u"Mackup" + assert cfg.directory == "Mackup" assert isinstance(cfg.fullpath, str) - assert cfg.fullpath.endswith(u"/Google Drive/Mackup") + assert cfg.fullpath.endswith("/Google Drive/Mackup") assert cfg.apps_to_ignore == set(["subversion", "sequel-pro", "sabnzbd"]) assert cfg.apps_to_sync == set(["sublime-text-3", "x11", "sabnzbd"]) @@ -137,13 +137,13 @@ def test_config_engine_copy(self): assert cfg.engine == ENGINE_COPY assert isinstance(cfg.path, str) - assert cfg.path == u"/Users/someuser/Copy" + assert cfg.path == "/Users/someuser/Copy" assert isinstance(cfg.directory, str) - assert cfg.directory == u"Mackup" + assert cfg.directory == "Mackup" assert isinstance(cfg.fullpath, str) - assert cfg.fullpath.endswith(u"/Copy/Mackup") + assert cfg.fullpath.endswith("/Copy/Mackup") assert cfg.apps_to_ignore == set(["subversion", "sequel-pro", "sabnzbd"]) assert cfg.apps_to_sync == set(["sublime-text-3", "x11", "sabnzbd"]) @@ -160,10 +160,10 @@ def test_config_engine_icloud(self): ) assert isinstance(cfg.directory, str) - assert cfg.directory == u"Mackup" + assert cfg.directory == "Mackup" assert isinstance(cfg.fullpath, str) - assert cfg.fullpath.endswith(u"/com~apple~CloudDocs/Mackup") + assert cfg.fullpath.endswith("/com~apple~CloudDocs/Mackup") assert cfg.apps_to_ignore == set(["subversion", "sequel-pro", "sabnzbd"]) assert cfg.apps_to_sync == set(["sublime-text-3", "x11", "sabnzbd"]) @@ -186,10 +186,10 @@ def test_config_apps_to_ignore(self): assert cfg.path == "/home/some_user/Dropbox" assert isinstance(cfg.directory, str) - assert cfg.directory == u"Mackup" + assert cfg.directory == "Mackup" assert isinstance(cfg.fullpath, str) - assert cfg.fullpath == u"/home/some_user/Dropbox/Mackup" + assert cfg.fullpath == "/home/some_user/Dropbox/Mackup" assert cfg.apps_to_ignore == set(["subversion", "sequel-pro", "sabnzbd"]) assert cfg.apps_to_sync == set() @@ -201,13 +201,13 @@ def test_config_apps_to_sync(self): assert cfg.engine == ENGINE_DROPBOX assert isinstance(cfg.path, str) - assert cfg.path == u"/home/some_user/Dropbox" + assert cfg.path == "/home/some_user/Dropbox" assert isinstance(cfg.directory, str) - assert cfg.directory == u"Mackup" + assert cfg.directory == "Mackup" assert isinstance(cfg.fullpath, str) - assert cfg.fullpath == u"/home/some_user/Dropbox/Mackup" + assert cfg.fullpath == "/home/some_user/Dropbox/Mackup" assert cfg.apps_to_ignore == set() assert cfg.apps_to_sync == set(["sabnzbd", "sublime-text-3", "x11"]) @@ -219,13 +219,13 @@ def test_config_apps_to_ignore_and_sync(self): assert cfg.engine == ENGINE_DROPBOX assert isinstance(cfg.path, str) - assert cfg.path == u"/home/some_user/Dropbox" + assert cfg.path == "/home/some_user/Dropbox" assert isinstance(cfg.directory, str) - assert cfg.directory == u"Mackup" + assert cfg.directory == "Mackup" assert isinstance(cfg.fullpath, str) - assert cfg.fullpath == u"/home/some_user/Dropbox/Mackup" + assert cfg.fullpath == "/home/some_user/Dropbox/Mackup" assert cfg.apps_to_ignore == set(["subversion", "sequel-pro", "sabnzbd"]) assert cfg.apps_to_sync == set(["sabnzbd", "sublime-text-3", "x11", "vim"]) diff --git a/tests/fixtures/Library/Application Support/Test App/2020/data.txt b/tests/fixtures/Library/Application Support/Test App/2020/data.txt new file mode 100644 index 000000000..e0fbadda9 --- /dev/null +++ b/tests/fixtures/Library/Application Support/Test App/2020/data.txt @@ -0,0 +1 @@ +2020 diff --git a/tests/fixtures/Library/Application Support/Test App/2021/data.txt b/tests/fixtures/Library/Application Support/Test App/2021/data.txt new file mode 100644 index 000000000..c533c5ee9 --- /dev/null +++ b/tests/fixtures/Library/Application Support/Test App/2021/data.txt @@ -0,0 +1 @@ +2021 diff --git a/tests/fixtures/Library/Application Support/Test App/2022/data.txt b/tests/fixtures/Library/Application Support/Test App/2022/data.txt new file mode 100644 index 000000000..cfa518059 --- /dev/null +++ b/tests/fixtures/Library/Application Support/Test App/2022/data.txt @@ -0,0 +1 @@ +2022 From acc8896b6d6ca5b4a4cb3337b6d5b53afb65b9eb Mon Sep 17 00:00:00 2001 From: Jim Neuendorf Date: Tue, 15 Mar 2022 00:05:16 +0100 Subject: [PATCH 05/16] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b987a2b2..c3cc7b710 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ - Added support for notion-enhancer (via @fharper) - Added support for GitFox (via @L3K0V) - Updated support for Bartender through SetApp (via @dbhagen) +- Added support for glob pattern in application config files (via @jneuendorf and @semkagtn) ## Mackup 0.8.33 From dddb822b73ce5a60080086a2ab6d6231525393e8 Mon Sep 17 00:00:00 2001 From: Jim Neuendorf Date: Tue, 15 Mar 2022 00:33:26 +0100 Subject: [PATCH 06/16] re-support python 2.7, remove traktor app --- mackup/applications/traktor.cfg | 8 -------- mackup/appsdb.py | 5 ++--- 2 files changed, 2 insertions(+), 11 deletions(-) delete mode 100644 mackup/applications/traktor.cfg diff --git a/mackup/applications/traktor.cfg b/mackup/applications/traktor.cfg deleted file mode 100644 index 1ef1bedd1..000000000 --- a/mackup/applications/traktor.cfg +++ /dev/null @@ -1,8 +0,0 @@ -[application] -name = Traktor - -[options] -enable_glob = true - -[configuration_files] -Documents/Native Instruments/Traktor *.*.*/Traktor Settings.tsi diff --git a/mackup/appsdb.py b/mackup/appsdb.py index 3b5cae52f..a191555de 100644 --- a/mackup/appsdb.py +++ b/mackup/appsdb.py @@ -6,7 +6,6 @@ """ import glob import os -from pathlib import Path try: import configparser @@ -180,8 +179,8 @@ def get_pretty_app_names(self): def get_resolves_paths(self, path, config): if config.getboolean("options", "enable_glob", fallback=False): return { - str(p.relative_to(os.environ["HOME"])) - for p in Path(os.environ["HOME"]).glob(path) + os.path.relpath(resolved_path, start=os.environ["HOME"]) + for resolved_path in glob.glob(os.path.join(os.environ["HOME"], path)) } else: return set([path]) From 135f8373171844b5b2d8cacf27b4bd06b0abcaf7 Mon Sep 17 00:00:00 2001 From: Jim Neuendorf Date: Tue, 15 Mar 2022 00:47:19 +0100 Subject: [PATCH 07/16] support python 2.7, lint --- CHANGELOG.md | 3 ++- tests/apps_config_tests.py | 44 ++++++++++++++++++++++++++------------ 2 files changed, 32 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c3cc7b710..29a1fccac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,8 @@ - Added support for notion-enhancer (via @fharper) - Added support for GitFox (via @L3K0V) - Updated support for Bartender through SetApp (via @dbhagen) -- Added support for glob pattern in application config files (via @jneuendorf and @semkagtn) +- Added support for glob pattern in application config files (via @jneuendorf + and @semkagtn) ## Mackup 0.8.33 diff --git a/tests/apps_config_tests.py b/tests/apps_config_tests.py index 4f4ac2b52..bd86df202 100644 --- a/tests/apps_config_tests.py +++ b/tests/apps_config_tests.py @@ -4,6 +4,12 @@ from unittest.mock import patch import stat +try: + from unittest.mock import patch +except ImportError: + patch = None + + from mackup import utils from mackup.appsdb import ApplicationsDatabase @@ -39,19 +45,29 @@ def tearDown(self): os.remove(self.config_file_path) def test_glob_configuration_paths(self): - with patch.object( - ApplicationsDatabase, - "get_config_files", - return_value=[self.config_file_path], - ) as method: + if patch: + with patch.object( + ApplicationsDatabase, + "get_config_files", + return_value=[self.config_file_path], + ) as method: + app_db = ApplicationsDatabase() + self.assertEqual( + app_db.get_files("test-app"), + { + "Library/Application Support/Test App/2020/data.txt", + "Library/Application Support/Test App/2021/data.txt", + "Library/Application Support/Test App/2022/data.txt", + }, + ) + else: app_db = ApplicationsDatabase() - print(app_db.apps) - + app_db.get_config_files = lambda *args, **kwargs: [self.config_file_path] self.assertEqual( - app_db.get_files("test-app"), - { - "Library/Application Support/Test App/2020/data.txt", - "Library/Application Support/Test App/2021/data.txt", - "Library/Application Support/Test App/2022/data.txt", - }, - ) + app_db.get_files("test-app"), + { + "Library/Application Support/Test App/2020/data.txt", + "Library/Application Support/Test App/2021/data.txt", + "Library/Application Support/Test App/2022/data.txt", + }, + ) From 5089f44af8355ee1cefd5da0bd37b7e6a8a2c9f6 Mon Sep 17 00:00:00 2001 From: Jim Neuendorf Date: Tue, 15 Mar 2022 00:50:16 +0100 Subject: [PATCH 08/16] fix pipeline --- .github/workflows/lint.yaml | 2 +- tests/apps_config_tests.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index 4502ca383..e839eae92 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -11,4 +11,4 @@ jobs: steps: - run: pip install black - uses: actions/checkout@v2 - - run: black --check --target-version py27 . + - run: black --check --target-version py34 . diff --git a/tests/apps_config_tests.py b/tests/apps_config_tests.py index bd86df202..a56cc6163 100644 --- a/tests/apps_config_tests.py +++ b/tests/apps_config_tests.py @@ -1,7 +1,6 @@ import os import tempfile import unittest -from unittest.mock import patch import stat try: From 53684769bf5882ba3db5fa274bb80ffcd9bf19cf Mon Sep 17 00:00:00 2001 From: Jim Neuendorf Date: Tue, 15 Mar 2022 00:56:25 +0100 Subject: [PATCH 09/16] lint, ascii config for python 2.7 --- tests/apps_config_tests.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/apps_config_tests.py b/tests/apps_config_tests.py index a56cc6163..52e36fe31 100644 --- a/tests/apps_config_tests.py +++ b/tests/apps_config_tests.py @@ -24,7 +24,7 @@ class TestMackup(unittest.TestCase): def setUp(self): os.environ["HOME"] = FIXTURES_DIR - with open(self.config_file_path, "w") as config_file: + with open(self.config_file_path, "wb") as config_file: config_file.write( "\n".join( [ @@ -37,7 +37,7 @@ def setUp(self): "[configuration_files]", "Library/Application Support/Test App/*/data.txt", ] - ) + ).encode("ascii") ) def tearDown(self): @@ -63,10 +63,10 @@ def test_glob_configuration_paths(self): app_db = ApplicationsDatabase() app_db.get_config_files = lambda *args, **kwargs: [self.config_file_path] self.assertEqual( - app_db.get_files("test-app"), - { - "Library/Application Support/Test App/2020/data.txt", - "Library/Application Support/Test App/2021/data.txt", - "Library/Application Support/Test App/2022/data.txt", - }, - ) + app_db.get_files("test-app"), + { + "Library/Application Support/Test App/2020/data.txt", + "Library/Application Support/Test App/2021/data.txt", + "Library/Application Support/Test App/2022/data.txt", + }, + ) From 8db489bc9727ec3d10dca0c7213b91a683d5cb2a Mon Sep 17 00:00:00 2001 From: Jim Neuendorf Date: Tue, 15 Mar 2022 01:08:03 +0100 Subject: [PATCH 10/16] fix python 2 unicode --- tests/apps_config_tests.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/apps_config_tests.py b/tests/apps_config_tests.py index 52e36fe31..5b8e6ce8f 100644 --- a/tests/apps_config_tests.py +++ b/tests/apps_config_tests.py @@ -24,7 +24,7 @@ class TestMackup(unittest.TestCase): def setUp(self): os.environ["HOME"] = FIXTURES_DIR - with open(self.config_file_path, "wb") as config_file: + with open(self.config_file_path, "w", encoding='utf-8') as config_file: config_file.write( "\n".join( [ @@ -37,7 +37,7 @@ def setUp(self): "[configuration_files]", "Library/Application Support/Test App/*/data.txt", ] - ).encode("ascii") + ) ) def tearDown(self): From 4aa356bdc72913f714d005a9d994e5e93ff94a3c Mon Sep 17 00:00:00 2001 From: Jim Neuendorf Date: Tue, 15 Mar 2022 01:11:11 +0100 Subject: [PATCH 11/16] .. --- tests/apps_config_tests.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/apps_config_tests.py b/tests/apps_config_tests.py index 5b8e6ce8f..f4e9ba14e 100644 --- a/tests/apps_config_tests.py +++ b/tests/apps_config_tests.py @@ -24,7 +24,7 @@ class TestMackup(unittest.TestCase): def setUp(self): os.environ["HOME"] = FIXTURES_DIR - with open(self.config_file_path, "w", encoding='utf-8') as config_file: + with open(self.config_file_path, "wb") as config_file: config_file.write( "\n".join( [ @@ -37,7 +37,7 @@ def setUp(self): "[configuration_files]", "Library/Application Support/Test App/*/data.txt", ] - ) + ).encode("utf-8") ) def tearDown(self): From 8c571fbab58f0216a2ca94d250374fa8c1d36ddf Mon Sep 17 00:00:00 2001 From: Jim Neuendorf Date: Tue, 15 Mar 2022 01:19:48 +0100 Subject: [PATCH 12/16] .. --- mackup/appsdb.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/mackup/appsdb.py b/mackup/appsdb.py index a191555de..7b5d32269 100644 --- a/mackup/appsdb.py +++ b/mackup/appsdb.py @@ -32,7 +32,13 @@ def __init__(self): # Needed to not lowercase the configuration_files in the ini files config.optionxform = str - if config.read(config_file): + try: + valid_config = config.read(config_file) + except UnicodeEncodeError: + with open(config_file, "r", "utf8") as fp: + valid_config = config.readfp(fp) + + if valid_config: # Get the filename without the directory name filename = os.path.basename(config_file) # The app name is the cfg filename without the extension From eb986107c6464c18c6f4c3556b5471fd5a895587 Mon Sep 17 00:00:00 2001 From: Jim Neuendorf Date: Tue, 15 Mar 2022 01:27:19 +0100 Subject: [PATCH 13/16] enhance makefile --- Makefile | 5 +++++ mackup/appsdb.py | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 2098f4cf7..b0d35507c 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,5 @@ +.PHONY: develop undevelop lint test clean release black prepare + develop: pipenv run python setup.py develop @@ -21,3 +23,6 @@ release: clean black: pipenv run black --target-version py34 . + +prepare: black test + diff --git a/mackup/appsdb.py b/mackup/appsdb.py index 7b5d32269..d05834ccd 100644 --- a/mackup/appsdb.py +++ b/mackup/appsdb.py @@ -4,6 +4,7 @@ The Applications Database provides an easy to use interface to load application data from the Mackup Database (files). """ +import codecs import glob import os @@ -35,7 +36,7 @@ def __init__(self): try: valid_config = config.read(config_file) except UnicodeEncodeError: - with open(config_file, "r", "utf8") as fp: + with codecs.open(config_file, "r", "utf8") as fp: valid_config = config.readfp(fp) if valid_config: From bdb8142ac16c8312fed0f3f1a892ab8a5b94ef0f Mon Sep 17 00:00:00 2001 From: Jim Neuendorf Date: Wed, 16 Mar 2022 23:31:09 +0100 Subject: [PATCH 14/16] update tests readme --- tests/README.md | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/tests/README.md b/tests/README.md index 3f24728db..5a896677f 100644 --- a/tests/README.md +++ b/tests/README.md @@ -14,9 +14,21 @@ make test And you should see ``` -. +................................ +Name Stmts Miss Branch BrPart Cover +--------------------------------------------------------- +mackup/__init__.py 0 0 0 0 100% +mackup/application.py 88 79 62 0 7% +mackup/appsdb.py 78 17 38 12 66% +mackup/config.py 92 3 34 2 96% +mackup/constants.py 15 0 0 0 100% +mackup/mackup.py 37 22 14 0 33% +mackup/main.py 77 61 32 0 17% +mackup/utils.py 148 7 58 13 90% +--------------------------------------------------------- +TOTAL 535 189 238 27 58% ---------------------------------------------------------------------- -Ran 1 test in 0.016s +Ran 32 tests in 0.178s OK ``` From 9ea6b88b429e050170e1fff2753356cfce45d243 Mon Sep 17 00:00:00 2001 From: Jim Neuendorf Date: Sat, 2 Apr 2022 22:54:18 +0200 Subject: [PATCH 15/16] adjust makefile phony targets --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 1a12a4e27..53a2a48a9 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: develop undevelop lint test clean release black prepare +.PHONY: develop undevelop lint test clean release black develop: pipenv run python setup.py develop From eecb47945400385f25e7b96adcf59f183403241b Mon Sep 17 00:00:00 2001 From: Jim Neuendorf Date: Sat, 9 Apr 2022 09:08:29 +0200 Subject: [PATCH 16/16] fix typo --- mackup/appsdb.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mackup/appsdb.py b/mackup/appsdb.py index d05834ccd..43e1373cc 100644 --- a/mackup/appsdb.py +++ b/mackup/appsdb.py @@ -60,7 +60,7 @@ def __init__(self): raise ValueError( "Unsupported absolute path: {}".format(path) ) - app["configuration_files"] |= self.get_resolves_paths( + app["configuration_files"] |= self.get_resolved_paths( path, config ) @@ -82,7 +82,7 @@ def __init__(self): ) path = os.path.join(xdg_config_home, path) path = path.replace(home, "") - app["configuration_files"] |= self.get_resolves_paths( + app["configuration_files"] |= self.get_resolved_paths( path, config ) @@ -183,7 +183,7 @@ def get_pretty_app_names(self): return pretty_app_names - def get_resolves_paths(self, path, config): + def get_resolved_paths(self, path, config): if config.getboolean("options", "enable_glob", fallback=False): return { os.path.relpath(resolved_path, start=os.environ["HOME"])