Diff
from v0.1.1 to v0.1.2
Diffstat
.gitignore | 19 -
Pipfile | 19 ++
Pipfile.lock | 287 ++++++++++++++++++++++++++++++++++++++
README.md | 22 +-
nnotes_cli/__init__.py | 11 +
nnotes_cli/config.py | 27 --
nnotes_cli/nextcloud_note.py | 45 +++--
nnotes_cli/nncli.py | 38 +++-
requirements.txt | 2
setup.cfg | 12 +
setup.py | 8
tests/test_config.py | 99 +++++++++++++
tests/test_nncli.py | 278 ++++++++++++++++++++++++++++++++++++
tests/test_version.py | 35 ++++
.gitignore
1 |
|
-# byte-compiled python files |
2 |
|
-*.pyc |
3 |
|
- |
4 |
|
-# venv dirs |
5 |
|
-env/ |
6 |
|
-venv/ |
7 |
|
- |
8 |
|
-# python packaging files/dirs |
9 |
|
-build |
10 |
|
-dist |
|
1 |
+build/ |
|
2 |
+dist/ |
11 |
3 |
MANIFEST |
12 |
|
-*.egg-info/* |
13 |
|
- |
14 |
|
-.ropeproject |
|
4 |
+*.egg-info/ |
|
5 |
+nnotes_cli/version.py |
|
6 |
+.coverage |
|
7 |
+.pytest_cache/ |
Pipfile (created)
|
1 |
+[[source]] |
|
2 |
+url = "https://pypi.org/simple" |
|
3 |
+verify_ssl = true |
|
4 |
+name = "pypi" |
|
5 |
+ |
|
6 |
+[packages] |
|
7 |
+appdirs = "*" |
|
8 |
+requests = "*" |
|
9 |
+urwid = "*" |
|
10 |
+setuptools = "*" |
|
11 |
+setuptools-scm = "*" |
|
12 |
+ |
|
13 |
+[dev-packages] |
|
14 |
+pytest = "*" |
|
15 |
+pytest-cov = "*" |
|
16 |
+pytest-mock = "*" |
|
17 |
+pytest-runner = "*" |
|
18 |
+pylint = "*" |
|
19 |
+pudb = "*" |
Pipfile.lock (created)
|
1 |
+{ |
|
2 |
+ "_meta": { |
|
3 |
+ "hash": { |
|
4 |
+ "sha256": "b4bc66838172733ffa35a5998d87982699b21d67eccdb8d913fffd8c7dcd101a" |
|
5 |
+ }, |
|
6 |
+ "pipfile-spec": 6, |
|
7 |
+ "requires": {}, |
|
8 |
+ "sources": [ |
|
9 |
+ { |
|
10 |
+ "name": "pypi", |
|
11 |
+ "url": "https://pypi.org/simple", |
|
12 |
+ "verify_ssl": true |
|
13 |
+ } |
|
14 |
+ ] |
|
15 |
+ }, |
|
16 |
+ "default": { |
|
17 |
+ "appdirs": { |
|
18 |
+ "hashes": [ |
|
19 |
+ "sha256:9e5896d1372858f8dd3344faf4e5014d21849c756c8d5701f78f8a103b372d92", |
|
20 |
+ "sha256:d8b24664561d0d34ddfaec54636d502d7cea6e29c3eaf68f3df6180863e2166e" |
|
21 |
+ ], |
|
22 |
+ "index": "pypi", |
|
23 |
+ "version": "==1.4.3" |
|
24 |
+ }, |
|
25 |
+ "certifi": { |
|
26 |
+ "hashes": [ |
|
27 |
+ "sha256:376690d6f16d32f9d1fe8932551d80b23e9d393a8578c5633a2ed39a64861638", |
|
28 |
+ "sha256:456048c7e371c089d0a77a5212fb37a2c2dce1e24146e3b7e0261736aaeaa22a" |
|
29 |
+ ], |
|
30 |
+ "version": "==2018.8.24" |
|
31 |
+ }, |
|
32 |
+ "chardet": { |
|
33 |
+ "hashes": [ |
|
34 |
+ "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", |
|
35 |
+ "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" |
|
36 |
+ ], |
|
37 |
+ "version": "==3.0.4" |
|
38 |
+ }, |
|
39 |
+ "idna": { |
|
40 |
+ "hashes": [ |
|
41 |
+ "sha256:156a6814fb5ac1fc6850fb002e0852d56c0c8d2531923a51032d1b70760e186e", |
|
42 |
+ "sha256:684a38a6f903c1d71d6d5fac066b58d7768af4de2b832e426ec79c30daa94a16" |
|
43 |
+ ], |
|
44 |
+ "version": "==2.7" |
|
45 |
+ }, |
|
46 |
+ "requests": { |
|
47 |
+ "hashes": [ |
|
48 |
+ "sha256:63b52e3c866428a224f97cab011de738c36aec0185aa91cfacd418b5d58911d1", |
|
49 |
+ "sha256:ec22d826a36ed72a7358ff3fe56cbd4ba69dd7a6718ffd450ff0e9df7a47ce6a" |
|
50 |
+ ], |
|
51 |
+ "index": "pypi", |
|
52 |
+ "version": "==2.19.1" |
|
53 |
+ }, |
|
54 |
+ "setuptools-scm": { |
|
55 |
+ "hashes": [ |
|
56 |
+ "sha256:1191f2a136b5e86f7ca8ab00a97ef7aef997131f1f6d4971be69a1ef387d8b40", |
|
57 |
+ "sha256:cc6953d224a22f10e933fa2f55c95979317c55259016adcf93310ba2997febfa" |
|
58 |
+ ], |
|
59 |
+ "index": "pypi", |
|
60 |
+ "version": "==3.1.0" |
|
61 |
+ }, |
|
62 |
+ "urllib3": { |
|
63 |
+ "hashes": [ |
|
64 |
+ "sha256:a68ac5e15e76e7e5dd2b8f94007233e01effe3e50e8daddf69acfd81cb686baf", |
|
65 |
+ "sha256:b5725a0bd4ba422ab0e66e89e030c806576753ea3ee08554382c14e685d117b5" |
|
66 |
+ ], |
|
67 |
+ "markers": "python_version != '3.1.*' and python_version != '3.3.*' and python_version >= '2.6' and python_version != '3.0.*' and python_version != '3.2.*' and python_version < '4'", |
|
68 |
+ "version": "==1.23" |
|
69 |
+ }, |
|
70 |
+ "urwid": { |
|
71 |
+ "hashes": [ |
|
72 |
+ "sha256:644d3e3900867161a2fc9287a9762753d66bd194754679adb26aede559bcccbc" |
|
73 |
+ ], |
|
74 |
+ "index": "pypi", |
|
75 |
+ "version": "==2.0.1" |
|
76 |
+ } |
|
77 |
+ }, |
|
78 |
+ "develop": { |
|
79 |
+ "astroid": { |
|
80 |
+ "hashes": [ |
|
81 |
+ "sha256:292fa429e69d60e4161e7612cb7cc8fa3609e2e309f80c224d93a76d5e7b58be", |
|
82 |
+ "sha256:c7013d119ec95eb626f7a2011f0b63d0c9a095df9ad06d8507b37084eada1a8d" |
|
83 |
+ ], |
|
84 |
+ "version": "==2.0.4" |
|
85 |
+ }, |
|
86 |
+ "atomicwrites": { |
|
87 |
+ "hashes": [ |
|
88 |
+ "sha256:6b5282987b21cd79151f51caccead7a09d0a32e89c568bd9e3c4aaa7bbdf3f3a", |
|
89 |
+ "sha256:e16334d50fe0f90919ef7339c24b9b62e6abaa78cd2d226f3d94eb067eb89043" |
|
90 |
+ ], |
|
91 |
+ "markers": "python_version != '3.2.*' and python_version >= '2.7' and python_version != '3.1.*' and python_version != '3.3.*' and python_version != '3.0.*'", |
|
92 |
+ "version": "==1.2.0" |
|
93 |
+ }, |
|
94 |
+ "attrs": { |
|
95 |
+ "hashes": [ |
|
96 |
+ "sha256:4b90b09eeeb9b88c35bc642cbac057e45a5fd85367b985bd2809c62b7b939265", |
|
97 |
+ "sha256:e0d0eb91441a3b53dab4d9b743eafc1ac44476296a2053b6ca3af0b139faf87b" |
|
98 |
+ ], |
|
99 |
+ "version": "==18.1.0" |
|
100 |
+ }, |
|
101 |
+ "coverage": { |
|
102 |
+ "hashes": [ |
|
103 |
+ "sha256:03481e81d558d30d230bc12999e3edffe392d244349a90f4ef9b88425fac74ba", |
|
104 |
+ "sha256:0b136648de27201056c1869a6c0d4e23f464750fd9a9ba9750b8336a244429ed", |
|
105 |
+ "sha256:10a46017fef60e16694a30627319f38a2b9b52e90182dddb6e37dcdab0f4bf95", |
|
106 |
+ "sha256:198626739a79b09fa0a2f06e083ffd12eb55449b5f8bfdbeed1df4910b2ca640", |
|
107 |
+ "sha256:23d341cdd4a0371820eb2b0bd6b88f5003a7438bbedb33688cd33b8eae59affd", |
|
108 |
+ "sha256:28b2191e7283f4f3568962e373b47ef7f0392993bb6660d079c62bd50fe9d162", |
|
109 |
+ "sha256:2a5b73210bad5279ddb558d9a2bfedc7f4bf6ad7f3c988641d83c40293deaec1", |
|
110 |
+ "sha256:2eb564bbf7816a9d68dd3369a510be3327f1c618d2357fa6b1216994c2e3d508", |
|
111 |
+ "sha256:337ded681dd2ef9ca04ef5d93cfc87e52e09db2594c296b4a0a3662cb1b41249", |
|
112 |
+ "sha256:3a2184c6d797a125dca8367878d3b9a178b6fdd05fdc2d35d758c3006a1cd694", |
|
113 |
+ "sha256:3c79a6f7b95751cdebcd9037e4d06f8d5a9b60e4ed0cd231342aa8ad7124882a", |
|
114 |
+ "sha256:3d72c20bd105022d29b14a7d628462ebdc61de2f303322c0212a054352f3b287", |
|
115 |
+ "sha256:3eb42bf89a6be7deb64116dd1cc4b08171734d721e7a7e57ad64cc4ef29ed2f1", |
|
116 |
+ "sha256:4635a184d0bbe537aa185a34193898eee409332a8ccb27eea36f262566585000", |
|
117 |
+ "sha256:56e448f051a201c5ebbaa86a5efd0ca90d327204d8b059ab25ad0f35fbfd79f1", |
|
118 |
+ "sha256:5a13ea7911ff5e1796b6d5e4fbbf6952381a611209b736d48e675c2756f3f74e", |
|
119 |
+ "sha256:69bf008a06b76619d3c3f3b1983f5145c75a305a0fea513aca094cae5c40a8f5", |
|
120 |
+ "sha256:6bc583dc18d5979dc0f6cec26a8603129de0304d5ae1f17e57a12834e7235062", |
|
121 |
+ "sha256:701cd6093d63e6b8ad7009d8a92425428bc4d6e7ab8d75efbb665c806c1d79ba", |
|
122 |
+ "sha256:7608a3dd5d73cb06c531b8925e0ef8d3de31fed2544a7de6c63960a1e73ea4bc", |
|
123 |
+ "sha256:76ecd006d1d8f739430ec50cc872889af1f9c1b6b8f48e29941814b09b0fd3cc", |
|
124 |
+ "sha256:7aa36d2b844a3e4a4b356708d79fd2c260281a7390d678a10b91ca595ddc9e99", |
|
125 |
+ "sha256:7d3f553904b0c5c016d1dad058a7554c7ac4c91a789fca496e7d8347ad040653", |
|
126 |
+ "sha256:7e1fe19bd6dce69d9fd159d8e4a80a8f52101380d5d3a4d374b6d3eae0e5de9c", |
|
127 |
+ "sha256:8c3cb8c35ec4d9506979b4cf90ee9918bc2e49f84189d9bf5c36c0c1119c6558", |
|
128 |
+ "sha256:9d6dd10d49e01571bf6e147d3b505141ffc093a06756c60b053a859cb2128b1f", |
|
129 |
+ "sha256:be6cfcd8053d13f5f5eeb284aa8a814220c3da1b0078fa859011c7fffd86dab9", |
|
130 |
+ "sha256:c1bb572fab8208c400adaf06a8133ac0712179a334c09224fb11393e920abcdd", |
|
131 |
+ "sha256:de4418dadaa1c01d497e539210cb6baa015965526ff5afc078c57ca69160108d", |
|
132 |
+ "sha256:e05cb4d9aad6233d67e0541caa7e511fa4047ed7750ec2510d466e806e0255d6", |
|
133 |
+ "sha256:f3f501f345f24383c0000395b26b726e46758b71393267aeae0bd36f8b3ade80" |
|
134 |
+ ], |
|
135 |
+ "markers": "python_version < '4' and python_version != '3.2.*' and python_version != '3.0.*' and python_version != '3.1.*' and python_version >= '2.6'", |
|
136 |
+ "version": "==4.5.1" |
|
137 |
+ }, |
|
138 |
+ "isort": { |
|
139 |
+ "hashes": [ |
|
140 |
+ "sha256:1153601da39a25b14ddc54955dbbacbb6b2d19135386699e2ad58517953b34af", |
|
141 |
+ "sha256:b9c40e9750f3d77e6e4d441d8b0266cf555e7cdabdcff33c4fd06366ca761ef8", |
|
142 |
+ "sha256:ec9ef8f4a9bc6f71eec99e1806bfa2de401650d996c59330782b89a5555c1497" |
|
143 |
+ ], |
|
144 |
+ "markers": "python_version >= '2.7' and python_version != '3.3.*' and python_version != '3.2.*' and python_version != '3.0.*' and python_version != '3.1.*'", |
|
145 |
+ "version": "==4.3.4" |
|
146 |
+ }, |
|
147 |
+ "lazy-object-proxy": { |
|
148 |
+ "hashes": [ |
|
149 |
+ "sha256:0ce34342b419bd8f018e6666bfef729aec3edf62345a53b537a4dcc115746a33", |
|
150 |
+ "sha256:1b668120716eb7ee21d8a38815e5eb3bb8211117d9a90b0f8e21722c0758cc39", |
|
151 |
+ "sha256:209615b0fe4624d79e50220ce3310ca1a9445fd8e6d3572a896e7f9146bbf019", |
|
152 |
+ "sha256:27bf62cb2b1a2068d443ff7097ee33393f8483b570b475db8ebf7e1cba64f088", |
|
153 |
+ "sha256:27ea6fd1c02dcc78172a82fc37fcc0992a94e4cecf53cb6d73f11749825bd98b", |
|
154 |
+ "sha256:2c1b21b44ac9beb0fc848d3993924147ba45c4ebc24be19825e57aabbe74a99e", |
|
155 |
+ "sha256:2df72ab12046a3496a92476020a1a0abf78b2a7db9ff4dc2036b8dd980203ae6", |
|
156 |
+ "sha256:320ffd3de9699d3892048baee45ebfbbf9388a7d65d832d7e580243ade426d2b", |
|
157 |
+ "sha256:50e3b9a464d5d08cc5227413db0d1c4707b6172e4d4d915c1c70e4de0bbff1f5", |
|
158 |
+ "sha256:5276db7ff62bb7b52f77f1f51ed58850e315154249aceb42e7f4c611f0f847ff", |
|
159 |
+ "sha256:61a6cf00dcb1a7f0c773ed4acc509cb636af2d6337a08f362413c76b2b47a8dd", |
|
160 |
+ "sha256:6ae6c4cb59f199d8827c5a07546b2ab7e85d262acaccaacd49b62f53f7c456f7", |
|
161 |
+ "sha256:7661d401d60d8bf15bb5da39e4dd72f5d764c5aff5a86ef52a042506e3e970ff", |
|
162 |
+ "sha256:7bd527f36a605c914efca5d3d014170b2cb184723e423d26b1fb2fd9108e264d", |
|
163 |
+ "sha256:7cb54db3535c8686ea12e9535eb087d32421184eacc6939ef15ef50f83a5e7e2", |
|
164 |
+ "sha256:7f3a2d740291f7f2c111d86a1c4851b70fb000a6c8883a59660d95ad57b9df35", |
|
165 |
+ "sha256:81304b7d8e9c824d058087dcb89144842c8e0dea6d281c031f59f0acf66963d4", |
|
166 |
+ "sha256:933947e8b4fbe617a51528b09851685138b49d511af0b6c0da2539115d6d4514", |
|
167 |
+ "sha256:94223d7f060301b3a8c09c9b3bc3294b56b2188e7d8179c762a1cda72c979252", |
|
168 |
+ "sha256:ab3ca49afcb47058393b0122428358d2fbe0408cf99f1b58b295cfeb4ed39109", |
|
169 |
+ "sha256:bd6292f565ca46dee4e737ebcc20742e3b5be2b01556dafe169f6c65d088875f", |
|
170 |
+ "sha256:cb924aa3e4a3fb644d0c463cad5bc2572649a6a3f68a7f8e4fbe44aaa6d77e4c", |
|
171 |
+ "sha256:d0fc7a286feac9077ec52a927fc9fe8fe2fabab95426722be4c953c9a8bede92", |
|
172 |
+ "sha256:ddc34786490a6e4ec0a855d401034cbd1242ef186c20d79d2166d6a4bd449577", |
|
173 |
+ "sha256:e34b155e36fa9da7e1b7c738ed7767fc9491a62ec6af70fe9da4a057759edc2d", |
|
174 |
+ "sha256:e5b9e8f6bda48460b7b143c3821b21b452cb3a835e6bbd5dd33aa0c8d3f5137d", |
|
175 |
+ "sha256:e81ebf6c5ee9684be8f2c87563880f93eedd56dd2b6146d8a725b50b7e5adb0f", |
|
176 |
+ "sha256:eb91be369f945f10d3a49f5f9be8b3d0b93a4c2be8f8a5b83b0571b8123e0a7a", |
|
177 |
+ "sha256:f460d1ceb0e4a5dcb2a652db0904224f367c9b3c1470d5a7683c0480e582468b" |
|
178 |
+ ], |
|
179 |
+ "version": "==1.3.1" |
|
180 |
+ }, |
|
181 |
+ "mccabe": { |
|
182 |
+ "hashes": [ |
|
183 |
+ "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", |
|
184 |
+ "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f" |
|
185 |
+ ], |
|
186 |
+ "version": "==0.6.1" |
|
187 |
+ }, |
|
188 |
+ "more-itertools": { |
|
189 |
+ "hashes": [ |
|
190 |
+ "sha256:c187a73da93e7a8acc0001572aebc7e3c69daf7bf6881a2cea10650bd4420092", |
|
191 |
+ "sha256:c476b5d3a34e12d40130bc2f935028b5f636df8f372dc2c1c01dc19681b2039e", |
|
192 |
+ "sha256:fcbfeaea0be121980e15bc97b3817b5202ca73d0eae185b4550cbfce2a3ebb3d" |
|
193 |
+ ], |
|
194 |
+ "version": "==4.3.0" |
|
195 |
+ }, |
|
196 |
+ "pluggy": { |
|
197 |
+ "hashes": [ |
|
198 |
+ "sha256:6e3836e39f4d36ae72840833db137f7b7d35105079aee6ec4a62d9f80d594dd1", |
|
199 |
+ "sha256:95eb8364a4708392bae89035f45341871286a333f749c3141c20573d2b3876e1" |
|
200 |
+ ], |
|
201 |
+ "markers": "python_version != '3.0.*' and python_version != '3.2.*' and python_version != '3.1.*' and python_version != '3.3.*' and python_version >= '2.7'", |
|
202 |
+ "version": "==0.7.1" |
|
203 |
+ }, |
|
204 |
+ "pudb": { |
|
205 |
+ "hashes": [ |
|
206 |
+ "sha256:8d8b974641b7a7a2a721af01c9dce5eac8e05a2ceebc2680725ba8eef1ca876e" |
|
207 |
+ ], |
|
208 |
+ "index": "pypi", |
|
209 |
+ "version": "==2018.1" |
|
210 |
+ }, |
|
211 |
+ "py": { |
|
212 |
+ "hashes": [ |
|
213 |
+ "sha256:06a30435d058473046be836d3fc4f27167fd84c45b99704f2fb5509ef61f9af1", |
|
214 |
+ "sha256:50402e9d1c9005d759426988a492e0edaadb7f4e68bcddfea586bc7432d009c6" |
|
215 |
+ ], |
|
216 |
+ "markers": "python_version != '3.0.*' and python_version != '3.2.*' and python_version != '3.3.*' and python_version != '3.1.*' and python_version >= '2.7'", |
|
217 |
+ "version": "==1.6.0" |
|
218 |
+ }, |
|
219 |
+ "pygments": { |
|
220 |
+ "hashes": [ |
|
221 |
+ "sha256:78f3f434bcc5d6ee09020f92ba487f95ba50f1e3ef83ae96b9d5ffa1bab25c5d", |
|
222 |
+ "sha256:dbae1046def0efb574852fab9e90209b23f556367b5a320c0bcb871c77c3e8cc" |
|
223 |
+ ], |
|
224 |
+ "version": "==2.2.0" |
|
225 |
+ }, |
|
226 |
+ "pylint": { |
|
227 |
+ "hashes": [ |
|
228 |
+ "sha256:1d6d3622c94b4887115fe5204982eee66fdd8a951cf98635ee5caee6ec98c3ec", |
|
229 |
+ "sha256:31142f764d2a7cd41df5196f9933b12b7ee55e73ef12204b648ad7e556c119fb" |
|
230 |
+ ], |
|
231 |
+ "index": "pypi", |
|
232 |
+ "version": "==2.1.1" |
|
233 |
+ }, |
|
234 |
+ "pytest": { |
|
235 |
+ "hashes": [ |
|
236 |
+ "sha256:2e7c330338b2732ddb992217962e3454aa7290434e75329b1a6739cea41bea6b", |
|
237 |
+ "sha256:4abcd98faeea3eb95bd05aa6a7b121d5f89d72e4d36ddb0dcbbfd1ec9f3651d1" |
|
238 |
+ ], |
|
239 |
+ "index": "pypi", |
|
240 |
+ "version": "==3.7.3" |
|
241 |
+ }, |
|
242 |
+ "pytest-cov": { |
|
243 |
+ "hashes": [ |
|
244 |
+ "sha256:03aa752cf11db41d281ea1d807d954c4eda35cfa1b21d6971966cc041bbf6e2d", |
|
245 |
+ "sha256:890fe5565400902b0c78b5357004aab1c814115894f4f21370e2433256a3eeec" |
|
246 |
+ ], |
|
247 |
+ "index": "pypi", |
|
248 |
+ "version": "==2.5.1" |
|
249 |
+ }, |
|
250 |
+ "pytest-mock": { |
|
251 |
+ "hashes": [ |
|
252 |
+ "sha256:53801e621223d34724926a5c98bd90e8e417ce35264365d39d6c896388dcc928", |
|
253 |
+ "sha256:d89a8209d722b8307b5e351496830d5cc5e192336003a485443ae9adeb7dd4c0" |
|
254 |
+ ], |
|
255 |
+ "index": "pypi", |
|
256 |
+ "version": "==1.10.0" |
|
257 |
+ }, |
|
258 |
+ "pytest-runner": { |
|
259 |
+ "hashes": [ |
|
260 |
+ "sha256:d23f117be39919f00dd91bffeb4f15e031ec797501b717a245e377aee0f577be", |
|
261 |
+ "sha256:d987fec1e31287592ffe1cb823a8c613c533db4c6aaca0ee1191dbc91e2fcc61" |
|
262 |
+ ], |
|
263 |
+ "index": "pypi", |
|
264 |
+ "version": "==4.2" |
|
265 |
+ }, |
|
266 |
+ "six": { |
|
267 |
+ "hashes": [ |
|
268 |
+ "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9", |
|
269 |
+ "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb" |
|
270 |
+ ], |
|
271 |
+ "version": "==1.11.0" |
|
272 |
+ }, |
|
273 |
+ "urwid": { |
|
274 |
+ "hashes": [ |
|
275 |
+ "sha256:644d3e3900867161a2fc9287a9762753d66bd194754679adb26aede559bcccbc" |
|
276 |
+ ], |
|
277 |
+ "index": "pypi", |
|
278 |
+ "version": "==2.0.1" |
|
279 |
+ }, |
|
280 |
+ "wrapt": { |
|
281 |
+ "hashes": [ |
|
282 |
+ "sha256:d4d560d479f2c21e1b5443bbd15fe7ec4b37fe7e53d335d3b9b0a7b1226fe3c6" |
|
283 |
+ ], |
|
284 |
+ "version": "==1.10.11" |
|
285 |
+ } |
|
286 |
+ } |
|
287 |
+} |
README.md
1 |
1 |
nncli |
2 |
2 |
===== |
3 |
3 |
|
|
4 |
+ |
|
5 |
+[](https://pypi.org/project/nncli/) |
|
6 |
+ |
4 |
7 |
NextCloud Notes Command Line Interface |
5 |
8 |
|
6 |
9 |
nncli is a Python application that gives you access to your NextCloud |
|
|
. . . |
32 |
35 |
* Manually: |
33 |
36 |
- Clone this repository to your hard disk: `git clone |
34 |
37 |
https://github.com/djmoch/nncli.git` |
35 |
|
- - Install the requirements `pip3 install -r requirements.txt` |
36 |
38 |
- Install _nncli_: `python3 setup.py install` |
|
39 |
+* Development: |
|
40 |
+ - Clone the repo |
|
41 |
+ - Install Pipenv: `pip install pipenv` |
|
42 |
+ - Stand up development environment: `pipenv install --dev` |
37 |
43 |
|
38 |
44 |
### Features |
39 |
45 |
|
|
|
. . . |
81 |
87 |
-r, --regex - search string is a regular expression |
82 |
88 |
-k <key>, --key=<key> - note key |
83 |
89 |
-t <title>, --title=<title> - title of note for create (cli mode) |
84 |
|
- -c <file>, --config=<file> - config file to read from (defaults to |
85 |
|
- ~/.config/nncli/config) |
|
90 |
+ -c <file>, --config=<file> - config file to read from |
|
91 |
+ --version - version information |
86 |
92 |
|
87 |
93 |
COMMANDS: |
88 |
94 |
<none> - console gui mode when no command specified |
|
|
. . . |
109 |
115 |
accessible to nncli. Use of the `cfg_nn_password_eval` option is |
110 |
116 |
recommended (see below). |
111 |
117 |
|
112 |
|
-nncli pulls in configuration from the `config` file located in your |
113 |
|
-`$XDG_CONFIG_HOME/nncli` directory. (By default, |
114 |
|
-`XDG_CONFIG_HOME=$HOME/.config`.) At the very least, the following example |
115 |
|
-`config` will get you going (using your account information): |
|
118 |
+nncli pulls in configuration from the `config` file located in the |
|
119 |
+standard location for your platform. At the very least, the following |
|
120 |
+example `config` will get you going (using your account information): |
116 |
121 |
|
117 |
122 |
``` |
118 |
123 |
[nncli] |
|
|
. . . |
146 |
151 |
|
147 |
152 |
# see http://urwid.org/manual/userinput.html for examples of more key |
148 |
153 |
# combinations |
149 |
|
-kb_edit_note = space kb_page_down = ctrl f |
|
154 |
+kb_edit_note = space |
|
155 |
+kb_page_down = ctrl f |
150 |
156 |
|
151 |
157 |
# note that values must not be quoted |
152 |
158 |
clr_note_focus_bg = light blue |
nnotes_cli/__init__.py
|
1 |
+try: |
|
2 |
+ from . import version |
|
3 |
+ __version__ = version.version |
|
4 |
+except ImportError: |
|
5 |
+ try: |
|
6 |
+ from setuptools_scm import get_version |
|
7 |
+ __version__ = get_version(root='..', relative_to=__file__) |
|
8 |
+ except: |
|
9 |
+ __version__ = '??-dev' |
|
10 |
+ |
1 |
11 |
__productname__ = 'nncli' |
2 |
|
-__version__ = '0.1.1' |
3 |
12 |
__copyright__ = "Copyright (c) 2018 Daniel Moch" |
4 |
13 |
__author__ = "Daniel Moch" |
5 |
14 |
__author_email__ = "daniel@danielmoch.com" |
nnotes_cli/config.py
27 |
27 |
|
28 |
28 |
import os, sys, urwid, collections, configparser, subprocess |
29 |
29 |
|
|
30 |
+from appdirs import user_cache_dir, user_config_dir |
|
31 |
+ |
30 |
32 |
class Config: |
31 |
33 |
|
32 |
34 |
def __init__(self, custom_file=None): |
33 |
|
- self.home = os.path.abspath(os.path.expanduser('~')) |
34 |
|
- if 'XDG_CONFIG_HOME' in os.environ.keys(): |
35 |
|
- self.config_home = \ |
36 |
|
- os.path.join(os.environ['XDG_CONFIG_HOME'], 'nncli') |
37 |
|
- else: |
38 |
|
- self.config_home = \ |
39 |
|
- os.path.join( |
40 |
|
- os.path.expanduser('~'), |
41 |
|
- '.config', |
42 |
|
- 'nncli' |
43 |
|
- ) |
44 |
|
- if 'XDG_CACHE_HOME' in os.environ.keys(): |
45 |
|
- self.cache_home = \ |
46 |
|
- os.path.join(os.environ['XDG_CACHE_HOME'], 'nncli') |
47 |
|
- else: |
48 |
|
- self.cache_home = \ |
49 |
|
- os.path.join( |
50 |
|
- os.path.expanduser('~'), |
51 |
|
- '.cache', |
52 |
|
- 'nncli' |
53 |
|
- ) |
|
35 |
+ self.config_home = user_config_dir('nncli', 'djmoch') |
|
36 |
+ self.cache_home = user_cache_dir('nncli', 'djmoch') |
|
37 |
+ |
54 |
38 |
defaults = \ |
55 |
39 |
{ |
56 |
40 |
'cfg_nn_username' : '', |
57 |
41 |
'cfg_nn_password' : '', |
|
42 |
+ 'cfg_nn_password_eval' : '', |
58 |
43 |
'cfg_db_path' : self.cache_home, |
59 |
44 |
'cfg_search_categories' : 'yes', # with regex searches |
60 |
45 |
'cfg_sort_mode' : 'date', # 'alpha' or 'date' |
nnotes_cli/nextcloud_note.py
65 |
65 |
|
66 |
66 |
def __init__(self, username, password, host): |
67 |
67 |
""" object constructor """ |
68 |
|
- self.username = urllib.parse.quote(username) |
69 |
|
- self.password = urllib.parse.quote(password) |
70 |
|
- self.api_url = \ |
71 |
|
- 'https://{}:{}@{}/index.php/apps/notes/api/v0.2/notes'. \ |
72 |
|
- format(username, password, host) |
73 |
|
- self.sanitized_url = \ |
74 |
|
- 'https://{}:****@{}/index.php/apps/notes/api/v0.2/notes'. \ |
75 |
|
- format(username, host) |
|
68 |
+ self.username = username |
|
69 |
+ self.password = password |
|
70 |
+ self.url = \ |
|
71 |
+ 'https://{}/index.php/apps/notes/api/v0.2/notes'. \ |
|
72 |
+ format(host) |
76 |
73 |
self.status = 'offline' |
77 |
74 |
|
78 |
75 |
def get_note(self, noteid): |
|
|
. . . |
89 |
86 |
|
90 |
87 |
""" |
91 |
88 |
# request note |
92 |
|
- url = '{}/{}'.format(self.api_url, str(noteid)) |
93 |
|
- #logging.debug('REQUEST: ' + self.sanitized_url+params) |
|
89 |
+ url = '{}/{}'.format(self.url, str(noteid)) |
|
90 |
+ #logging.debug('REQUEST: ' + self.url+params) |
94 |
91 |
try: |
95 |
|
- res = requests.get(url) |
|
92 |
+ res = requests.get(url, auth=(self.username, self.password)) |
96 |
93 |
res.raise_for_status() |
97 |
94 |
note = res.json() |
98 |
95 |
self.status = 'online' |
|
|
. . . |
136 |
133 |
if 'modified' not in note: |
137 |
134 |
note["modified"] = int(time.time()) |
138 |
135 |
|
139 |
|
- url = '{}/{}'.format(self.api_url, note["id"]) |
|
136 |
+ url = '{}/{}'.format(self.url, note["id"]) |
140 |
137 |
del note["id"] |
141 |
138 |
else: |
142 |
|
- url = self.api_url |
|
139 |
+ url = self.url |
143 |
140 |
|
144 |
141 |
#logging.debug('REQUEST: ' + url + ' - ' + str(note)) |
145 |
142 |
try: |
146 |
143 |
logging.debug('NOTE: ' + str(note)) |
147 |
|
- if url != self.api_url: |
148 |
|
- res = requests.put(url, data=note) |
|
144 |
+ if url != self.url: |
|
145 |
+ res = requests.put(url, auth=(self.username, |
|
146 |
+ self.password), json=note) |
149 |
147 |
else: |
150 |
|
- res = requests.post(url, data=note) |
|
148 |
+ res = requests.post(url, auth=(self.username, |
|
149 |
+ self.password), json=note) |
151 |
150 |
note = res.json() |
152 |
151 |
res.raise_for_status() |
153 |
152 |
logging.debug('NOTE (from response): ' + str(res.json())) |
|
|
. . . |
219 |
218 |
|
220 |
219 |
# perform initial HTTP request |
221 |
220 |
try: |
222 |
|
- logging.debug('REQUEST: ' + self.sanitized_url + \ |
|
221 |
+ logging.debug('REQUEST: ' + self.url + \ |
223 |
222 |
'?exclude=content') |
224 |
|
- res = requests.get(self.api_url, params=params) |
|
223 |
+ res = requests.get(self.url, auth=(self.username, self.password), params=params) |
225 |
224 |
res.raise_for_status() |
226 |
225 |
#logging.debug('RESPONSE OK: ' + str(res)) |
227 |
226 |
note_list = res.json() |
228 |
227 |
self.status = 'online' |
229 |
228 |
except ConnectionError as e: |
|
229 |
+ logging.exception('connection error') |
230 |
230 |
self.status = 'offline, connection error' |
231 |
231 |
status = -1 |
232 |
232 |
except RequestException as e: |
233 |
233 |
# if problem with network request/response |
|
234 |
+ logging.exception('request error') |
234 |
235 |
status = -1 |
235 |
236 |
except ValueError as e: |
236 |
237 |
# if invalid json data |
237 |
238 |
status = -1 |
|
239 |
+ logging.exception('request returned bad JSON data') |
238 |
240 |
|
239 |
241 |
# Can only filter for category at end, once all notes have been |
240 |
242 |
# retrieved. Below based on simplenote.vim, except we return |
|
|
. . . |
258 |
260 |
- status (int): 0 on sucesss and -1 otherwise |
259 |
261 |
|
260 |
262 |
""" |
261 |
|
- url = '{}/{}'.format(self.api_url, str(note['id'])) |
262 |
|
- logurl = '{}/{}'.format(self.sanitized_url, str(note['id'])) |
|
263 |
+ url = '{}/{}'.format(self.url, str(note['id'])) |
263 |
264 |
|
264 |
265 |
try: |
265 |
|
- logging.debug('REQUEST DELETE: ' + logurl) |
266 |
|
- res = requests.delete(url) |
|
266 |
+ logging.debug('REQUEST DELETE: ' + url) |
|
267 |
+ res = requests.delete(url, auth=(self.username, self.password)) |
267 |
268 |
res.raise_for_status() |
268 |
269 |
self.status = 'online' |
269 |
270 |
except ConnectionError as e: |
nnotes_cli/nncli.py
28 |
28 |
import os, sys, getopt, re, signal, time, datetime, shlex, hashlib |
29 |
29 |
import subprocess, threading, logging |
30 |
30 |
import copy, json, urwid, datetime |
|
31 |
+import nnotes_cli |
31 |
32 |
from . import view_titles, view_note, view_help, view_log, user_input |
32 |
33 |
from . import utils, temp |
33 |
34 |
from .config import Config |
|
|
. . . |
1145 |
1146 |
-r, --regex - search string is a regular expression |
1146 |
1147 |
-k <key>, --key=<key> - note key |
1147 |
1148 |
-t <title>, --title=<title> - title of note for create (cli mode) |
1148 |
|
- -c <file>, --config=<file> - config file to read from (defaults to |
1149 |
|
- ~/.config/nncli/config) |
|
1149 |
+ -c <file>, --config=<file> - config file to read from |
|
1150 |
+ -V, --version - version information |
1150 |
1151 |
|
1151 |
1152 |
COMMANDS: |
1152 |
1153 |
<none> - console gui mode when no command specified |
1153 |
1154 |
sync - perform a full sync with the server |
1154 |
1155 |
list [search_string] - list notes (refined with search string) |
1155 |
|
- export [search_string] - export notes in JSON (refined with search string) |
|
1156 |
+ export [search_string] - export notes in JSON (refined with search |
|
1157 |
+ string) |
1156 |
1158 |
dump [search_string] - dump notes (refined with search string) |
1157 |
1159 |
create [-] - create a note ('-' content from stdin) |
1158 |
|
- import [-] - import a note in JSON format ('-' JSON from stdin) |
1159 |
|
- export - export a note in JSON format (specified by <key>) |
|
1160 |
+ import [-] - import a note in JSON format ('-' JSON from |
|
1161 |
+ stdin) |
|
1162 |
+ export - export a note in JSON format (specified by |
|
1163 |
+ <key>) |
1160 |
1164 |
dump - dump a note (specified by <key>) |
1161 |
1165 |
edit - edit a note (specified by <key>) |
1162 |
1166 |
delete - delete a note (specified by <key>) |
1163 |
1167 |
< favorite | unfavorite > - favorite/unfavorite a note (specified by <key>) |
1164 |
|
- cat get - retrieve the category from a note (specified by <key>) |
|
1168 |
+ cat get - retrieve the category from a note (specified |
|
1169 |
+ by <key>) |
1165 |
1170 |
cat set <category> - set the category for a note (specified by <key>) |
1166 |
1171 |
cat rm - remove category from a note (specified by <key>) |
1167 |
1172 |
''') |
1168 |
1173 |
sys.exit(0) |
1169 |
1174 |
|
|
1175 |
+def version(): |
|
1176 |
+ version_info = '' |
|
1177 |
+ version_info += nnotes_cli.__productname__ + ' v' + \ |
|
1178 |
+ nnotes_cli.__version__ + "\n" |
|
1179 |
+ version_info += nnotes_cli.__description__ + "\n\n" |
|
1180 |
+ version_info += nnotes_cli.__copyright__ + "\n" |
|
1181 |
+ version_info += "Written by " + nnotes_cli.__author__ + \ |
|
1182 |
+ " and others\n" |
|
1183 |
+ version_info += "Licensed under the terms of the " + \ |
|
1184 |
+ nnotes_cli.__license__ + " license\n" |
|
1185 |
+ version_info += "The latest code is available at: " + \ |
|
1186 |
+ nnotes_cli.__url__ |
|
1187 |
+ print(version_info) |
|
1188 |
+ exit(0) |
1170 |
1189 |
|
1171 |
1190 |
def main(argv=sys.argv[1:]): |
1172 |
1191 |
verbose = False |
|
|
. . . |
1178 |
1197 |
|
1179 |
1198 |
try: |
1180 |
1199 |
opts, args = getopt.getopt(argv, |
1181 |
|
- 'hvnrk:t:c:', |
1182 |
|
- [ 'help', 'verbose', 'nosync', 'regex', 'key=', 'title=', 'config=' ]) |
|
1200 |
+ 'hvnrk:t:c:V', |
|
1201 |
+ [ 'help', 'verbose', 'nosync', 'regex', 'key=', 'title=', \ |
|
1202 |
+ 'config=', 'version' ]) |
1183 |
1203 |
except: |
1184 |
1204 |
usage() |
1185 |
1205 |
|
1186 |
1206 |
for opt, arg in opts: |
1187 |
1207 |
if opt in [ '-h', '--help']: |
1188 |
1208 |
usage() |
|
1209 |
+ elif opt in ['-V', '--version' ]: |
|
1210 |
+ version() |
1189 |
1211 |
elif opt in [ '-v', '--verbose']: |
1190 |
1212 |
verbose = True |
1191 |
1213 |
elif opt in [ '-n', '--nosync']: |
requirements.txt (deleted)
setup.cfg (created)
|
1 |
+[aliases] |
|
2 |
+test=pytest |
|
3 |
+ |
|
4 |
+[tool:pytest] |
|
5 |
+testpaths = tests |
|
6 |
+addopts = --cov=nnotes_cli --cov-report=term-missing |
|
7 |
+ |
|
8 |
+[yapf] |
|
9 |
+coalesce_brackets = true |
|
10 |
+dedent_closing_brackets = true |
|
11 |
+space_between_ending_comma_and_closing_bracket = false |
|
12 |
+split_arguments_when_comma_terminated = true |
setup.py
1 |
|
-#!/usr/bin/env python3 |
2 |
1 |
# |
3 |
2 |
# The MIT License (MIT) |
4 |
3 |
# |
|
|
. . . |
29 |
28 |
from setuptools import setup |
30 |
29 |
import nnotes_cli |
31 |
30 |
|
32 |
|
-deps = ['urwid', 'requests'] |
|
31 |
+deps = ['urwid', 'requests', 'appdirs'] |
|
32 |
+test_deps = ['pytest', 'pytest-cov', 'pytest-runner', 'pytest-mock'] |
33 |
33 |
|
34 |
34 |
with open("README.md", "r") as fh: |
35 |
35 |
long_description = fh.read() |
|
|
. . . |
39 |
39 |
description=nnotes_cli.__description__, |
40 |
40 |
long_description=long_description, |
41 |
41 |
long_description_content_type="text/markdown", |
42 |
|
- version=nnotes_cli.__version__, |
43 |
42 |
author=nnotes_cli.__author__, |
44 |
43 |
author_email=nnotes_cli.__author_email__, |
45 |
44 |
url=nnotes_cli.__url__, |
46 |
45 |
license=nnotes_cli.__license__, |
47 |
46 |
requires=deps, |
48 |
47 |
install_requires=deps, |
|
48 |
+ tests_require=test_deps, |
|
49 |
+ use_scm_version= {'write_to': 'nnotes_cli/version.py'}, |
|
50 |
+ setup_requires=['setuptools_scm'], |
49 |
51 |
packages=['nnotes_cli'], |
50 |
52 |
entry_points={ |
51 |
53 |
'console_scripts': [ |
tests/test_config.py (created)
|
1 |
+# |
|
2 |
+# The MIT License (MIT) |
|
3 |
+# |
|
4 |
+# Copyright (c) 2018 Daniel Moch |
|
5 |
+# |
|
6 |
+# Permission is hereby granted, free of charge, to any person obtaining a copy |
|
7 |
+# of this software and associated documentation files (the "Software"), to deal |
|
8 |
+# in the Software without restriction, including without limitation the rights |
|
9 |
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
10 |
+# copies of the Software, and to permit persons to whom the Software is |
|
11 |
+# furnished to do so, subject to the following conditions: |
|
12 |
+# |
|
13 |
+# The above copyright notice and this permission notice shall be included in all |
|
14 |
+# copies or substantial portions of the Software. |
|
15 |
+# |
|
16 |
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
17 |
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
18 |
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|
19 |
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
20 |
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
21 |
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|
22 |
+# SOFTWARE. |
|
23 |
+# |
|
24 |
+import os |
|
25 |
+import sys |
|
26 |
+ |
|
27 |
+from nnotes_cli.config import Config |
|
28 |
+from pytest import raises |
|
29 |
+ |
|
30 |
+def test_init(): |
|
31 |
+ config = Config() |
|
32 |
+ |
|
33 |
+ if sys.platform == 'linux': |
|
34 |
+ assert config.config_home == os.path.join(os.path.expanduser('~'), \ |
|
35 |
+ '.config', 'nncli') |
|
36 |
+ assert config.cache_home == os.path.join(os.path.expanduser('~'), \ |
|
37 |
+ '.cache', 'nncli') |
|
38 |
+ if sys.platform == 'darwin': |
|
39 |
+ assert config.config_home == os.path.join(os.path.expanduser('~'), \ |
|
40 |
+ 'Library', 'Preferences', 'nncli') |
|
41 |
+ assert config.cache_home == os.path.join(os.path.expanduser('~'), \ |
|
42 |
+ 'Library', 'Caches', 'nncli') |
|
43 |
+ |
|
44 |
+ |
|
45 |
+def test_custom_file(): |
|
46 |
+ with open('test_cfg', 'w') as config_file: |
|
47 |
+ config_file.write('[nncli]\n') |
|
48 |
+ config_file.write('cfg_nn_username=user\n') |
|
49 |
+ config_file.write('cfg_nn_password=password\n') |
|
50 |
+ config_file.write('cfg_nn_host=nextcloud.example.org\n') |
|
51 |
+ |
|
52 |
+ config = Config('test_cfg') |
|
53 |
+ os.remove('test_cfg') |
|
54 |
+ |
|
55 |
+def test_bad_password_eval(): |
|
56 |
+ with open('test_cfg', 'w') as config_file: |
|
57 |
+ config_file.write('[nncli]\n') |
|
58 |
+ config_file.write('cfg_nn_username=user\n') |
|
59 |
+ config_file.write('cfg_nn_password_eval=password\n') |
|
60 |
+ config_file.write('cfg_nn_host=nextcloud.example.org\n') |
|
61 |
+ |
|
62 |
+ with raises(SystemExit): |
|
63 |
+ config = Config('test_cfg') |
|
64 |
+ os.remove('test_cfg') |
|
65 |
+ |
|
66 |
+def test_empty_config(): |
|
67 |
+ with open('test_cfg', 'w') as config_file: |
|
68 |
+ config_file.write('\n') |
|
69 |
+ |
|
70 |
+ config = Config('test_cfg') |
|
71 |
+ os.remove('test_cfg') |
|
72 |
+ |
|
73 |
+def test_get_config(): |
|
74 |
+ config = Config('test_cfg') |
|
75 |
+ assert config.get_config('sort_mode') == 'date' |
|
76 |
+ |
|
77 |
+def test_get_config_descr(): |
|
78 |
+ config = Config('test_cfg') |
|
79 |
+ assert config.get_config_descr('sort_mode') == 'Sort mode' |
|
80 |
+ |
|
81 |
+def test_get_keybind(): |
|
82 |
+ config = Config('test_cfg') |
|
83 |
+ assert config.get_keybind('help') == 'h' |
|
84 |
+ |
|
85 |
+def test_get_keybind_use(): |
|
86 |
+ config = Config('test_cfg') |
|
87 |
+ assert config.get_keybind_use('help') == [ 'common' ] |
|
88 |
+ |
|
89 |
+def test_get_keybind_descr(): |
|
90 |
+ config = Config('test_cfg') |
|
91 |
+ assert config.get_keybind_descr('help') == 'Help' |
|
92 |
+ |
|
93 |
+def test_get_color(): |
|
94 |
+ config = Config('test_cfg') |
|
95 |
+ assert config.get_color('default_fg') == 'default' |
|
96 |
+ |
|
97 |
+def test_get_color_descr(): |
|
98 |
+ config = Config('test_cfg') |
|
99 |
+ assert config.get_color_descr('default_fg') == 'Default fg' |
tests/test_nncli.py (created)
|
1 |
+# |
|
2 |
+# The MIT License (MIT) |
|
3 |
+# |
|
4 |
+# Copyright (c) 2018 Daniel Moch |
|
5 |
+# |
|
6 |
+# Permission is hereby granted, free of charge, to any person obtaining a copy |
|
7 |
+# of this software and associated documentation files (the "Software"), to deal |
|
8 |
+# in the Software without restriction, including without limitation the rights |
|
9 |
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
10 |
+# copies of the Software, and to permit persons to whom the Software is |
|
11 |
+# furnished to do so, subject to the following conditions: |
|
12 |
+# |
|
13 |
+# The above copyright notice and this permission notice shall be included in all |
|
14 |
+# copies or substantial portions of the Software. |
|
15 |
+# |
|
16 |
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
17 |
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
18 |
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|
19 |
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
20 |
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
21 |
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|
22 |
+# SOFTWARE. |
|
23 |
+# |
|
24 |
+import logging |
|
25 |
+import os |
|
26 |
+import pytest |
|
27 |
+import shutil |
|
28 |
+ |
|
29 |
+from logging.handlers import RotatingFileHandler |
|
30 |
+from nnotes_cli.nncli import nncli |
|
31 |
+ |
|
32 |
+def mock_nncli(mocker): |
|
33 |
+ mocker.patch('logging.getLogger') |
|
34 |
+ mocker.patch('nnotes_cli.config.Config') |
|
35 |
+ mocker.patch('nnotes_cli.notes_db.NotesDB') |
|
36 |
+ mocker.patch('os.mkdir') |
|
37 |
+ mocker.patch.object(RotatingFileHandler, '_open') |
|
38 |
+ |
|
39 |
+def assert_initialized(): |
|
40 |
+ logging.getLogger.assert_called_once() |
|
41 |
+ RotatingFileHandler._open.assert_called_once() |
|
42 |
+ assert os.mkdir.call_count == 2 |
|
43 |
+ |
|
44 |
+@pytest.mark.parametrize('mock_nncli', [mock_nncli]) |
|
45 |
+def test_init_no_tempdir(mocker, mock_nncli): |
|
46 |
+ mock_nncli(mocker) |
|
47 |
+ |
|
48 |
+ with open('test_cfg', 'w') as config_file: |
|
49 |
+ config_file.write('[nncli]\n') |
|
50 |
+ config_file.write('cfg_db_path=duh') |
|
51 |
+ |
|
52 |
+ nn = nncli(False, config_file='test_cfg') |
|
53 |
+ assert_initialized() |
|
54 |
+ assert nn.tempdir == None |
|
55 |
+ os.mkdir.assert_called_with('duh') |
|
56 |
+ |
|
57 |
+ os.remove('test_cfg') |
|
58 |
+ |
|
59 |
+@pytest.mark.parametrize('mock_nncli', [mock_nncli]) |
|
60 |
+def test_init(mocker, mock_nncli): |
|
61 |
+ mock_nncli(mocker) |
|
62 |
+ |
|
63 |
+ with open('test_cfg', 'w') as config_file: |
|
64 |
+ config_file.write('[nncli]\n') |
|
65 |
+ config_file.write('cfg_tempdir=blah\n') |
|
66 |
+ config_file.write('cfg_db_path=duh') |
|
67 |
+ |
|
68 |
+ nn = nncli(False, config_file='test_cfg') |
|
69 |
+ assert_initialized() |
|
70 |
+ assert nn.tempdir == 'blah' |
|
71 |
+ |
|
72 |
+ os.remove('test_cfg') |
|
73 |
+ |
|
74 |
+@pytest.mark.parametrize('mock_nncli', [mock_nncli]) |
|
75 |
+def test_init_notesdb_fail(mocker, mock_nncli): |
|
76 |
+ os.mkdir('duh') |
|
77 |
+ mock_nncli(mocker) |
|
78 |
+ |
|
79 |
+ with open('duh/1.json', 'w') as bad_file: |
|
80 |
+ bad_file.write('bad_json_data') |
|
81 |
+ |
|
82 |
+ with open('test_cfg', 'w') as config_file: |
|
83 |
+ config_file.write('[nncli]\n') |
|
84 |
+ config_file.write('cfg_db_path=duh') |
|
85 |
+ |
|
86 |
+ with pytest.raises(SystemExit): |
|
87 |
+ nn = nncli(False, config_file='test_cfg') |
|
88 |
+ |
|
89 |
+ shutil.rmtree('duh') |
|
90 |
+ |
|
91 |
+@pytest.mark.parametrize('mock_nncli', [mock_nncli]) |
|
92 |
+def test_get_editor(mocker, mock_nncli): |
|
93 |
+ mock_nncli(mocker) |
|
94 |
+ |
|
95 |
+ with open('test_cfg', 'w') as config_file: |
|
96 |
+ config_file.write('[nncli]\n') |
|
97 |
+ config_file.write('cfg_db_path=duh') |
|
98 |
+ config_file.write('cfg_editor=vim') |
|
99 |
+ |
|
100 |
+ nn = nncli(False, config_file='test_cfg') |
|
101 |
+ assert_initialized() |
|
102 |
+ assert nn.get_editor() == 'vim' |
|
103 |
+ |
|
104 |
+ os.remove('test_cfg') |
|
105 |
+ |
|
106 |
+@pytest.mark.parametrize('mock_nncli', [mock_nncli]) |
|
107 |
+def test_no_editor(mocker, mock_nncli): |
|
108 |
+ mock_nncli(mocker) |
|
109 |
+ |
|
110 |
+ with open('test_cfg', 'w') as config_file: |
|
111 |
+ config_file.write('[nncli]\n') |
|
112 |
+ config_file.write('cfg_db_path=duh') |
|
113 |
+ |
|
114 |
+ nn = nncli(False, config_file='test_cfg') |
|
115 |
+ nn.config.configs['editor'] = [''] |
|
116 |
+ assert_initialized() |
|
117 |
+ assert nn.get_editor() == None |
|
118 |
+ |
|
119 |
+ os.remove('test_cfg') |
|
120 |
+ |
|
121 |
+def test_get_pager(): |
|
122 |
+ pass |
|
123 |
+ |
|
124 |
+def test_get_diff(): |
|
125 |
+ pass |
|
126 |
+ |
|
127 |
+def test_exec_cmd_on_note(): |
|
128 |
+ pass |
|
129 |
+ |
|
130 |
+def test_exec_diff_on_note(): |
|
131 |
+ pass |
|
132 |
+ |
|
133 |
+def test_gui_header_clear(): |
|
134 |
+ pass |
|
135 |
+ |
|
136 |
+def test_gui_header_set(): |
|
137 |
+ pass |
|
138 |
+ |
|
139 |
+def test_gui_header_get(): |
|
140 |
+ pass |
|
141 |
+ |
|
142 |
+def test_gui_header_focus(): |
|
143 |
+ pass |
|
144 |
+ |
|
145 |
+def test_gui_footer_log_clear(): |
|
146 |
+ pass |
|
147 |
+ |
|
148 |
+def test_gui_footer_log_set(): |
|
149 |
+ pass |
|
150 |
+ |
|
151 |
+def test_gui_footer_log_get(): |
|
152 |
+ pass |
|
153 |
+ |
|
154 |
+def test_gui_footer_input_clear(): |
|
155 |
+ pass |
|
156 |
+ |
|
157 |
+def test_gui_footer_input_set(): |
|
158 |
+ pass |
|
159 |
+ |
|
160 |
+def test_gui_footer_input_get(): |
|
161 |
+ pass |
|
162 |
+ |
|
163 |
+def test_gui_footer_focus_input(): |
|
164 |
+ pass |
|
165 |
+ |
|
166 |
+def test_gui_body_clear(): |
|
167 |
+ pass |
|
168 |
+ |
|
169 |
+def test_gui_body_set(): |
|
170 |
+ pass |
|
171 |
+ |
|
172 |
+def test_gui_body_get(): |
|
173 |
+ pass |
|
174 |
+ |
|
175 |
+def test_gui_body_focus(): |
|
176 |
+ pass |
|
177 |
+ |
|
178 |
+def test_log_timeout(): |
|
179 |
+ pass |
|
180 |
+ |
|
181 |
+def test_log(): |
|
182 |
+ pass |
|
183 |
+ |
|
184 |
+def test_gui_update_view(): |
|
185 |
+ pass |
|
186 |
+ |
|
187 |
+def test_gui_update_status_bar(): |
|
188 |
+ pass |
|
189 |
+ |
|
190 |
+def test_gui_switch_frame_body(): |
|
191 |
+ pass |
|
192 |
+ |
|
193 |
+def test_delete_note_callback(): |
|
194 |
+ pass |
|
195 |
+ |
|
196 |
+def test_gui_yes_no_input(): |
|
197 |
+ pass |
|
198 |
+ |
|
199 |
+def test_gui_search_input(): |
|
200 |
+ pass |
|
201 |
+ |
|
202 |
+def test_gui_category_input(): |
|
203 |
+ pass |
|
204 |
+ |
|
205 |
+def test_gui_pipe_input(): |
|
206 |
+ pass |
|
207 |
+ |
|
208 |
+def test_gui_frame_keypress(): |
|
209 |
+ pass |
|
210 |
+ |
|
211 |
+def test_gui_init_view(): |
|
212 |
+ pass |
|
213 |
+ |
|
214 |
+def test_gui_clear(): |
|
215 |
+ pass |
|
216 |
+ |
|
217 |
+def test_gui_reset(): |
|
218 |
+ pass |
|
219 |
+ |
|
220 |
+def test_gui_stop(): |
|
221 |
+ pass |
|
222 |
+ |
|
223 |
+def test_gui(): |
|
224 |
+ pass |
|
225 |
+ |
|
226 |
+def test_cli_list_notes(): |
|
227 |
+ pass |
|
228 |
+ |
|
229 |
+def test_cli_note_dump(): |
|
230 |
+ pass |
|
231 |
+ |
|
232 |
+def test_cli_dump_notes(): |
|
233 |
+ pass |
|
234 |
+ |
|
235 |
+def test_cli_note_create(): |
|
236 |
+ pass |
|
237 |
+ |
|
238 |
+def test_cli_note_import(): |
|
239 |
+ pass |
|
240 |
+ |
|
241 |
+def test_cli_note_export(): |
|
242 |
+ pass |
|
243 |
+ |
|
244 |
+def test_cli_export_notes(): |
|
245 |
+ pass |
|
246 |
+ |
|
247 |
+def test_cli_note_edit(): |
|
248 |
+ pass |
|
249 |
+ |
|
250 |
+def test_cli_note_delete(): |
|
251 |
+ pass |
|
252 |
+ |
|
253 |
+def test_cli_note_favorite(): |
|
254 |
+ pass |
|
255 |
+ |
|
256 |
+def test_cli_note_category_get(): |
|
257 |
+ pass |
|
258 |
+ |
|
259 |
+def test_cli_note_category_set(): |
|
260 |
+ pass |
|
261 |
+ |
|
262 |
+def test_cli_note_category_rm(): |
|
263 |
+ pass |
|
264 |
+ |
|
265 |
+def test_SIGINT_handler(): |
|
266 |
+ pass |
|
267 |
+ |
|
268 |
+def test_usage(): |
|
269 |
+ pass |
|
270 |
+ |
|
271 |
+def test_version(): |
|
272 |
+ pass |
|
273 |
+ |
|
274 |
+def test_main(): |
|
275 |
+ pass |
|
276 |
+ |
|
277 |
+def test_nncli_start(): |
|
278 |
+ pass |
tests/test_version.py (created)
|
1 |
+# |
|
2 |
+# The MIT License (MIT) |
|
3 |
+# |
|
4 |
+# Copyright (c) 2018 Daniel Moch |
|
5 |
+# |
|
6 |
+# Permission is hereby granted, free of charge, to any person obtaining a copy |
|
7 |
+# of this software and associated documentation files (the "Software"), to deal |
|
8 |
+# in the Software without restriction, including without limitation the rights |
|
9 |
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
10 |
+# copies of the Software, and to permit persons to whom the Software is |
|
11 |
+# furnished to do so, subject to the following conditions: |
|
12 |
+# |
|
13 |
+# The above copyright notice and this permission notice shall be included in all |
|
14 |
+# copies or substantial portions of the Software. |
|
15 |
+# |
|
16 |
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
17 |
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
18 |
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|
19 |
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
20 |
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
21 |
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|
22 |
+# SOFTWARE. |
|
23 |
+# |
|
24 |
+import nnotes_cli |
|
25 |
+import pytest |
|
26 |
+ |
|
27 |
+from nnotes_cli import version |
|
28 |
+from setuptools_scm import get_version |
|
29 |
+ |
|
30 |
+@pytest.mark.skip(reason="test_version will fail outside of a Git repo") |
|
31 |
+def test_version(): |
|
32 |
+ vers = get_version(root="..", relative_to=__file__) |
|
33 |
+ |
|
34 |
+ assert nnotes_cli.__version__ == vers |
|
35 |
+ assert version.version == vers |