ae-pythonanywhere 0.3.1__tar.gz → 0.3.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ae_pythonanywhere-0.3.1 → ae_pythonanywhere-0.3.3}/LICENSE.md +1 -1
- {ae_pythonanywhere-0.3.1/ae_pythonanywhere.egg-info → ae_pythonanywhere-0.3.3}/PKG-INFO +9 -10
- {ae_pythonanywhere-0.3.1 → ae_pythonanywhere-0.3.3}/README.md +5 -5
- {ae_pythonanywhere-0.3.1 → ae_pythonanywhere-0.3.3}/ae/pythonanywhere.py +3 -15
- {ae_pythonanywhere-0.3.1 → ae_pythonanywhere-0.3.3/ae_pythonanywhere.egg-info}/PKG-INFO +9 -10
- {ae_pythonanywhere-0.3.1 → ae_pythonanywhere-0.3.3}/ae_pythonanywhere.egg-info/requires.txt +2 -3
- {ae_pythonanywhere-0.3.1 → ae_pythonanywhere-0.3.3}/pyproject.toml +1 -1
- {ae_pythonanywhere-0.3.1 → ae_pythonanywhere-0.3.3}/setup.py +11 -11
- {ae_pythonanywhere-0.3.1 → ae_pythonanywhere-0.3.3}/tests/test_pythonanywhere.py +136 -24
- {ae_pythonanywhere-0.3.1 → ae_pythonanywhere-0.3.3}/ae_pythonanywhere.egg-info/SOURCES.txt +0 -0
- {ae_pythonanywhere-0.3.1 → ae_pythonanywhere-0.3.3}/ae_pythonanywhere.egg-info/dependency_links.txt +0 -0
- {ae_pythonanywhere-0.3.1 → ae_pythonanywhere-0.3.3}/ae_pythonanywhere.egg-info/top_level.txt +0 -0
- {ae_pythonanywhere-0.3.1 → ae_pythonanywhere-0.3.3}/ae_pythonanywhere.egg-info/zip-safe +0 -0
- {ae_pythonanywhere-0.3.1 → ae_pythonanywhere-0.3.3}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ae_pythonanywhere
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.3
|
|
4
4
|
Summary: ae namespace module portion pythonanywhere: PythonAnywhere Web API Client
|
|
5
5
|
Home-page: https://gitlab.com/ae-group/ae_pythonanywhere
|
|
6
6
|
Author: AndiEcker
|
|
@@ -16,7 +16,7 @@ Classifier: Natural Language :: English
|
|
|
16
16
|
Classifier: Operating System :: OS Independent
|
|
17
17
|
Classifier: Programming Language :: Python
|
|
18
18
|
Classifier: Programming Language :: Python :: 3
|
|
19
|
-
Classifier: Programming Language :: Python :: 3.
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
20
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
21
|
Classifier: Typing :: Typed
|
|
22
22
|
Requires-Python: >=3.9
|
|
@@ -26,13 +26,12 @@ Requires-Dist: requests
|
|
|
26
26
|
Requires-Dist: types-requests
|
|
27
27
|
Requires-Dist: ae_base
|
|
28
28
|
Requires-Dist: ae_paths
|
|
29
|
-
Requires-Dist: ae_dev_ops
|
|
30
29
|
Provides-Extra: dev
|
|
31
30
|
Requires-Dist: aedev_project_tpls; extra == "dev"
|
|
32
31
|
Requires-Dist: ae_ae; extra == "dev"
|
|
33
32
|
Requires-Dist: anybadge; extra == "dev"
|
|
34
33
|
Requires-Dist: coverage-badge; extra == "dev"
|
|
35
|
-
Requires-Dist:
|
|
34
|
+
Requires-Dist: aedev_project_manager; extra == "dev"
|
|
36
35
|
Requires-Dist: flake8; extra == "dev"
|
|
37
36
|
Requires-Dist: mypy; extra == "dev"
|
|
38
37
|
Requires-Dist: pylint; extra == "dev"
|
|
@@ -45,7 +44,7 @@ Provides-Extra: docs
|
|
|
45
44
|
Provides-Extra: tests
|
|
46
45
|
Requires-Dist: anybadge; extra == "tests"
|
|
47
46
|
Requires-Dist: coverage-badge; extra == "tests"
|
|
48
|
-
Requires-Dist:
|
|
47
|
+
Requires-Dist: aedev_project_manager; extra == "tests"
|
|
49
48
|
Requires-Dist: flake8; extra == "tests"
|
|
50
49
|
Requires-Dist: mypy; extra == "tests"
|
|
51
50
|
Requires-Dist: pylint; extra == "tests"
|
|
@@ -69,15 +68,15 @@ Dynamic: requires-dist
|
|
|
69
68
|
Dynamic: requires-python
|
|
70
69
|
Dynamic: summary
|
|
71
70
|
|
|
72
|
-
<!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project ae.ae v0.3.
|
|
73
|
-
<!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project aedev.namespace_root_tpls v0.3.
|
|
74
|
-
# pythonanywhere 0.3.
|
|
71
|
+
<!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project ae.ae v0.3.101 -->
|
|
72
|
+
<!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project aedev.namespace_root_tpls v0.3.22 -->
|
|
73
|
+
# pythonanywhere 0.3.3
|
|
75
74
|
|
|
76
75
|
[](
|
|
77
76
|
https://gitlab.com/ae-group/ae_pythonanywhere)
|
|
78
77
|
[](
|
|
79
|
+
https://gitlab.com/ae-group/ae_pythonanywhere/-/tree/release0.3.3)
|
|
81
80
|
[](
|
|
82
81
|
https://pypi.org/project/ae-pythonanywhere/#history)
|
|
83
82
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
<!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project ae.ae v0.3.
|
|
2
|
-
<!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project aedev.namespace_root_tpls v0.3.
|
|
3
|
-
# pythonanywhere 0.3.
|
|
1
|
+
<!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project ae.ae v0.3.101 -->
|
|
2
|
+
<!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project aedev.namespace_root_tpls v0.3.22 -->
|
|
3
|
+
# pythonanywhere 0.3.3
|
|
4
4
|
|
|
5
5
|
[](
|
|
6
6
|
https://gitlab.com/ae-group/ae_pythonanywhere)
|
|
7
7
|
[](
|
|
9
|
+
https://gitlab.com/ae-group/ae_pythonanywhere/-/tree/release0.3.3)
|
|
10
10
|
[](
|
|
11
11
|
https://pypi.org/project/ae-pythonanywhere/#history)
|
|
12
12
|
|
|
@@ -38,8 +38,6 @@ the following examples demonstrate key functionality, including how to initializ
|
|
|
38
38
|
the :class:`PythonanywhereApi` and list deployed files/folders, excluding common
|
|
39
39
|
temporary directories::
|
|
40
40
|
|
|
41
|
-
.. code-block:: python
|
|
42
|
-
|
|
43
41
|
from ae.paths import Collector
|
|
44
42
|
from ae.pythonanywhere import PythonanywhereApi
|
|
45
43
|
|
|
@@ -69,13 +67,13 @@ temporary directories::
|
|
|
69
67
|
else:
|
|
70
68
|
print("No files found or project directory is empty.")
|
|
71
69
|
|
|
70
|
+
|
|
72
71
|
more useful methods
|
|
73
72
|
-------------------
|
|
74
73
|
|
|
75
74
|
the most useful methods of the :class:`PythonanywhereAPI` class are (check the source code for more):~
|
|
76
75
|
|
|
77
76
|
* :meth:`~PythonanywhereAPI.deployed_file_content`: determine the file content of a file, deployed to the web server.
|
|
78
|
-
* :meth:`~PythonanywhereAPI.deployed_version`: determine the version of the deployed django project package.
|
|
79
77
|
* :meth:`~PythonanywhereAPI.deploy_file`: add or update a project file to the web server.
|
|
80
78
|
* :meth:`~PythonanywhereAPI.delete_file_or_folder`: delete a file or folder on the web server.
|
|
81
79
|
|
|
@@ -94,12 +92,11 @@ from typing import Any, Callable, Container, Iterable, Optional, Union, cast
|
|
|
94
92
|
|
|
95
93
|
import requests
|
|
96
94
|
|
|
97
|
-
from ae.base import
|
|
95
|
+
from ae.base import ErrorMsgMixin # type: ignore
|
|
98
96
|
from ae.paths import Collector, CollYieldItems, SearcherRetType, coll_items # type: ignore
|
|
99
|
-
from ae.dev_ops import code_version # type: ignore
|
|
100
97
|
|
|
101
98
|
|
|
102
|
-
__version__ = '0.3.
|
|
99
|
+
__version__ = '0.3.3'
|
|
103
100
|
|
|
104
101
|
|
|
105
102
|
class PythonanywhereApi(ErrorMsgMixin): # pylint: disable=too-many-instance-attributes
|
|
@@ -299,15 +296,6 @@ class PythonanywhereApi(ErrorMsgMixin): # pylint: disable=too-many-instance-a
|
|
|
299
296
|
return None
|
|
300
297
|
return response.content
|
|
301
298
|
|
|
302
|
-
def deployed_version(self) -> str:
|
|
303
|
-
""" determine the version of a deployed django project package.
|
|
304
|
-
|
|
305
|
-
:return: version string of the package deployed to the web host/server
|
|
306
|
-
or empty string if package version file or version-in-file not found.
|
|
307
|
-
"""
|
|
308
|
-
init_file_content = self.deployed_file_content(os.path.join(self.project_name, PY_INIT))
|
|
309
|
-
return "" if init_file_content is None else code_version(init_file_content)
|
|
310
|
-
|
|
311
299
|
def deploy_file(self, file_path: str, file_content: bytes) -> str:
|
|
312
300
|
""" add or update a project file to the web server.
|
|
313
301
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ae_pythonanywhere
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.3
|
|
4
4
|
Summary: ae namespace module portion pythonanywhere: PythonAnywhere Web API Client
|
|
5
5
|
Home-page: https://gitlab.com/ae-group/ae_pythonanywhere
|
|
6
6
|
Author: AndiEcker
|
|
@@ -16,7 +16,7 @@ Classifier: Natural Language :: English
|
|
|
16
16
|
Classifier: Operating System :: OS Independent
|
|
17
17
|
Classifier: Programming Language :: Python
|
|
18
18
|
Classifier: Programming Language :: Python :: 3
|
|
19
|
-
Classifier: Programming Language :: Python :: 3.
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
20
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
21
|
Classifier: Typing :: Typed
|
|
22
22
|
Requires-Python: >=3.9
|
|
@@ -26,13 +26,12 @@ Requires-Dist: requests
|
|
|
26
26
|
Requires-Dist: types-requests
|
|
27
27
|
Requires-Dist: ae_base
|
|
28
28
|
Requires-Dist: ae_paths
|
|
29
|
-
Requires-Dist: ae_dev_ops
|
|
30
29
|
Provides-Extra: dev
|
|
31
30
|
Requires-Dist: aedev_project_tpls; extra == "dev"
|
|
32
31
|
Requires-Dist: ae_ae; extra == "dev"
|
|
33
32
|
Requires-Dist: anybadge; extra == "dev"
|
|
34
33
|
Requires-Dist: coverage-badge; extra == "dev"
|
|
35
|
-
Requires-Dist:
|
|
34
|
+
Requires-Dist: aedev_project_manager; extra == "dev"
|
|
36
35
|
Requires-Dist: flake8; extra == "dev"
|
|
37
36
|
Requires-Dist: mypy; extra == "dev"
|
|
38
37
|
Requires-Dist: pylint; extra == "dev"
|
|
@@ -45,7 +44,7 @@ Provides-Extra: docs
|
|
|
45
44
|
Provides-Extra: tests
|
|
46
45
|
Requires-Dist: anybadge; extra == "tests"
|
|
47
46
|
Requires-Dist: coverage-badge; extra == "tests"
|
|
48
|
-
Requires-Dist:
|
|
47
|
+
Requires-Dist: aedev_project_manager; extra == "tests"
|
|
49
48
|
Requires-Dist: flake8; extra == "tests"
|
|
50
49
|
Requires-Dist: mypy; extra == "tests"
|
|
51
50
|
Requires-Dist: pylint; extra == "tests"
|
|
@@ -69,15 +68,15 @@ Dynamic: requires-dist
|
|
|
69
68
|
Dynamic: requires-python
|
|
70
69
|
Dynamic: summary
|
|
71
70
|
|
|
72
|
-
<!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project ae.ae v0.3.
|
|
73
|
-
<!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project aedev.namespace_root_tpls v0.3.
|
|
74
|
-
# pythonanywhere 0.3.
|
|
71
|
+
<!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project ae.ae v0.3.101 -->
|
|
72
|
+
<!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project aedev.namespace_root_tpls v0.3.22 -->
|
|
73
|
+
# pythonanywhere 0.3.3
|
|
75
74
|
|
|
76
75
|
[](
|
|
77
76
|
https://gitlab.com/ae-group/ae_pythonanywhere)
|
|
78
77
|
[](
|
|
79
|
+
https://gitlab.com/ae-group/ae_pythonanywhere/-/tree/release0.3.3)
|
|
81
80
|
[](
|
|
82
81
|
https://pypi.org/project/ae-pythonanywhere/#history)
|
|
83
82
|
|
|
@@ -2,14 +2,13 @@ requests
|
|
|
2
2
|
types-requests
|
|
3
3
|
ae_base
|
|
4
4
|
ae_paths
|
|
5
|
-
ae_dev_ops
|
|
6
5
|
|
|
7
6
|
[dev]
|
|
8
7
|
aedev_project_tpls
|
|
9
8
|
ae_ae
|
|
10
9
|
anybadge
|
|
11
10
|
coverage-badge
|
|
12
|
-
|
|
11
|
+
aedev_project_manager
|
|
13
12
|
flake8
|
|
14
13
|
mypy
|
|
15
14
|
pylint
|
|
@@ -24,7 +23,7 @@ types-setuptools
|
|
|
24
23
|
[tests]
|
|
25
24
|
anybadge
|
|
26
25
|
coverage-badge
|
|
27
|
-
|
|
26
|
+
aedev_project_manager
|
|
28
27
|
flake8
|
|
29
28
|
mypy
|
|
30
29
|
pylint
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# THIS FILE IS EXCLUSIVELY MAINTAINED by the project aedev.project_tpls v0.3.
|
|
1
|
+
# THIS FILE IS EXCLUSIVELY MAINTAINED by the project aedev.project_tpls v0.3.68
|
|
2
2
|
""" setup of ae namespace module portion pythonanywhere: PythonAnywhere Web API Client. """
|
|
3
3
|
# noinspection PyUnresolvedReferences
|
|
4
4
|
import sys
|
|
@@ -12,26 +12,26 @@ setup_kwargs = {
|
|
|
12
12
|
'author_email': 'aecker2@gmail.com',
|
|
13
13
|
'classifiers': [ 'Development Status :: 3 - Alpha', 'Natural Language :: English', 'Operating System :: OS Independent',
|
|
14
14
|
'Programming Language :: Python', 'Programming Language :: Python :: 3',
|
|
15
|
-
'Programming Language :: Python :: 3.
|
|
15
|
+
'Programming Language :: Python :: 3.12', 'Topic :: Software Development :: Libraries :: Python Modules',
|
|
16
16
|
'Typing :: Typed'],
|
|
17
17
|
'description': 'ae namespace module portion pythonanywhere: PythonAnywhere Web API Client',
|
|
18
|
-
'extras_require': { 'dev': [ 'aedev_project_tpls', 'ae_ae', 'anybadge', 'coverage-badge', '
|
|
18
|
+
'extras_require': { 'dev': [ 'aedev_project_tpls', 'ae_ae', 'anybadge', 'coverage-badge', 'aedev_project_manager', 'flake8',
|
|
19
19
|
'mypy', 'pylint', 'pytest', 'pytest-cov', 'pytest-django', 'typing', 'types-setuptools'],
|
|
20
20
|
'docs': [],
|
|
21
|
-
'tests': [ 'anybadge', 'coverage-badge', '
|
|
21
|
+
'tests': [ 'anybadge', 'coverage-badge', 'aedev_project_manager', 'flake8', 'mypy', 'pylint', 'pytest',
|
|
22
22
|
'pytest-cov', 'pytest-django', 'typing', 'types-setuptools']},
|
|
23
|
-
'install_requires': ['requests', 'types-requests', 'ae_base', 'ae_paths'
|
|
23
|
+
'install_requires': ['requests', 'types-requests', 'ae_base', 'ae_paths'],
|
|
24
24
|
'keywords': ['configuration', 'development', 'environment', 'productivity'],
|
|
25
25
|
'license': 'GPL-3.0-or-later',
|
|
26
|
-
'long_description': ('<!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project ae.ae v0.3.
|
|
27
|
-
'<!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project aedev.namespace_root_tpls v0.3.
|
|
28
|
-
'# pythonanywhere 0.3.
|
|
26
|
+
'long_description': ('<!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project ae.ae v0.3.101 -->\n'
|
|
27
|
+
'<!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project aedev.namespace_root_tpls v0.3.22 -->\n'
|
|
28
|
+
'# pythonanywhere 0.3.3\n'
|
|
29
29
|
'\n'
|
|
30
30
|
'[](\n'
|
|
31
31
|
' https://gitlab.com/ae-group/ae_pythonanywhere)\n'
|
|
32
32
|
'[](\n'
|
|
34
|
+
' https://gitlab.com/ae-group/ae_pythonanywhere/-/tree/release0.3.3)\n'
|
|
35
35
|
'[](\n'
|
|
36
36
|
' https://pypi.org/project/ae-pythonanywhere/#history)\n'
|
|
37
37
|
'\n'
|
|
@@ -108,7 +108,7 @@ setup_kwargs = {
|
|
|
108
108
|
'Source': 'https://ae.readthedocs.io/en/latest/_modules/ae/pythonanywhere.html'},
|
|
109
109
|
'python_requires': '>=3.9',
|
|
110
110
|
'url': 'https://gitlab.com/ae-group/ae_pythonanywhere',
|
|
111
|
-
'version': '0.3.
|
|
111
|
+
'version': '0.3.3',
|
|
112
112
|
'zip_safe': True,
|
|
113
113
|
}
|
|
114
114
|
|
|
@@ -1,27 +1,31 @@
|
|
|
1
|
-
""" unit tests
|
|
1
|
+
""" unit and integration tests of the ae_pythonanywhere module package.
|
|
2
2
|
|
|
3
|
-
minimal testing because of the rate-limits on pythonanywhere.com (each endpoint has a 40
|
|
4
|
-
apart from the send_input endpoint on consoles, which is 120 requests per minute - see
|
|
3
|
+
minimal and only local integration testing because of the rate-limits on pythonanywhere.com (each endpoint has a 40
|
|
4
|
+
requests per minute rate limit, apart from the send_input endpoint on consoles, which is 120 requests per minute - see
|
|
5
5
|
`https://help.pythonanywhere.com/pages/API`__ for more details).
|
|
6
6
|
"""
|
|
7
7
|
import os
|
|
8
8
|
import pytest
|
|
9
9
|
import requests
|
|
10
10
|
|
|
11
|
-
from conftest import skip_gitlab_ci
|
|
12
11
|
from unittest.mock import Mock, patch
|
|
13
12
|
|
|
14
|
-
from
|
|
15
|
-
|
|
13
|
+
from conftest import skip_gitlab_ci
|
|
14
|
+
|
|
15
|
+
from ae.base import PY_CACHE_FOLDER, PY_INIT, load_dotenvs, norm_name, os_path_join
|
|
16
|
+
from ae.shell import get_domain_user_var
|
|
16
17
|
from ae.pythonanywhere import PythonanywhereApi
|
|
17
18
|
|
|
18
19
|
|
|
19
|
-
|
|
20
|
+
TST_DOMAIN_NAME = 'python_anywhere.tst'
|
|
21
|
+
TST_USER_NAME = 'py_any_user'
|
|
22
|
+
TST_WEB_TOKEN = 'py_any_token'
|
|
23
|
+
TST_PROJECT_NAME = 'ae_pythonanywhere_tests' #: package name used for local unit and integration tests
|
|
20
24
|
|
|
21
|
-
pkg0_ini_path = os.path.join(
|
|
25
|
+
pkg0_ini_path = os.path.join(TST_PROJECT_NAME, PY_INIT)
|
|
22
26
|
pkg0_version = '333.66.9'
|
|
23
27
|
pkg0_ini_content = f'""" test package doc string. """\n\n__version__ = \'{pkg0_version}\'\n'.encode()
|
|
24
|
-
pkg0_static_file = f'{
|
|
28
|
+
pkg0_static_file = f'{TST_PROJECT_NAME}/static/baseball.html'
|
|
25
29
|
|
|
26
30
|
pkg1_name = "test_pkg1"
|
|
27
31
|
pkg1_file_path = f'{pkg1_name}/namespace_mod.py'
|
|
@@ -51,24 +55,28 @@ skipped_lean_paths = {'not_deployed_root_file.xxx',
|
|
|
51
55
|
all_file_paths = all_pkg_paths | skipped_web_paths | skipped_lean_paths | static_file_paths
|
|
52
56
|
|
|
53
57
|
|
|
58
|
+
@pytest.fixture
|
|
59
|
+
def api_obj():
|
|
60
|
+
yield PythonanywhereApi(TST_DOMAIN_NAME, TST_USER_NAME, TST_WEB_TOKEN, TST_PROJECT_NAME)
|
|
61
|
+
|
|
62
|
+
|
|
54
63
|
@pytest.fixture(scope='class')
|
|
55
64
|
def connection():
|
|
56
|
-
"""
|
|
57
|
-
|
|
58
|
-
load_dotenvs(main_app)
|
|
65
|
+
""" pythonanywhere remote web server connection for integration tests, only run locally using .env credentials. """
|
|
66
|
+
load_dotenvs()
|
|
59
67
|
|
|
60
68
|
web_domain = "www.pythonanywhere.com"
|
|
61
69
|
web_user = os.environ.get('PDV_AUTHOR')
|
|
62
|
-
web_token =
|
|
70
|
+
web_token = get_domain_user_var('web_token', domain=web_domain, user=web_user)
|
|
63
71
|
|
|
64
|
-
remote_connection = PythonanywhereApi(web_domain, web_user, web_token,
|
|
72
|
+
remote_connection = PythonanywhereApi(web_domain, web_user, web_token, TST_PROJECT_NAME)
|
|
65
73
|
|
|
66
74
|
yield remote_connection
|
|
67
75
|
|
|
68
76
|
|
|
69
77
|
@pytest.fixture(scope='class')
|
|
70
78
|
def con_pkg(connection):
|
|
71
|
-
""" provide personal pythonanywhere remote web server connection plus test package for tests """
|
|
79
|
+
""" provide personal pythonanywhere remote web server connection plus test package for integration tests """
|
|
72
80
|
del_fil = 'test0/sub4/del_file.txt'
|
|
73
81
|
assert not connection.deploy_file(del_fil, b"deleted to test empty root folder")
|
|
74
82
|
assert connection.error_message == ""
|
|
@@ -91,13 +99,118 @@ def test_pythonanywhere_declarations():
|
|
|
91
99
|
""" test the module declarations (also for having at least one test case running on gitlab ci). """
|
|
92
100
|
assert PythonanywhereApi
|
|
93
101
|
|
|
94
|
-
assert norm_name(
|
|
102
|
+
assert norm_name(TST_PROJECT_NAME) == TST_PROJECT_NAME
|
|
95
103
|
|
|
96
104
|
assert requests # not-used-inspection-warning workaround, used for requests.Response.json() patching
|
|
97
105
|
|
|
98
106
|
|
|
107
|
+
class TestPythonanywhereApi:
|
|
108
|
+
def test_instantiation(self, api_obj):
|
|
109
|
+
assert TST_DOMAIN_NAME in api_obj.base_url
|
|
110
|
+
assert TST_USER_NAME == api_obj.web_user
|
|
111
|
+
assert TST_USER_NAME in api_obj.base_url
|
|
112
|
+
assert TST_USER_NAME in api_obj.pkg_files_url_part
|
|
113
|
+
assert TST_WEB_TOKEN in api_obj.protocol_headers['Authorization']
|
|
114
|
+
assert TST_PROJECT_NAME == api_obj.project_name
|
|
115
|
+
assert TST_PROJECT_NAME in api_obj.pkg_files_url_part
|
|
116
|
+
|
|
117
|
+
def test_project_name_setter(self, api_obj):
|
|
118
|
+
api_obj.project_name = 'new-prj-name'
|
|
119
|
+
|
|
120
|
+
assert 'new-prj-name' == api_obj.project_name
|
|
121
|
+
assert 'new-prj-name' in api_obj.pkg_files_url_part
|
|
122
|
+
|
|
123
|
+
def test__folder_items(self, api_obj):
|
|
124
|
+
response_mock = Mock(status_code=200, json=lambda: {'file-name': {'type': 'file-type'}})
|
|
125
|
+
with patch('ae.pythonanywhere.PythonanywhereApi._request', return_value=response_mock):
|
|
126
|
+
ret = api_obj._folder_items('folder-path')
|
|
127
|
+
assert isinstance(ret, list) and len(ret) == 1
|
|
128
|
+
assert ret[0]['file_path'] == os_path_join('folder-path', 'file-name')
|
|
129
|
+
assert ret[0]['type'] == 'file-type'
|
|
130
|
+
assert not api_obj.error_message # 404 error gets reset
|
|
131
|
+
|
|
132
|
+
def test__folder_items_err_inexistent_file_path(self, api_obj):
|
|
133
|
+
assert api_obj._folder_items('inexistent_file_path') is None
|
|
134
|
+
assert api_obj.error_message
|
|
135
|
+
|
|
136
|
+
def test__folder_items_err_inexistent_folder(self, api_obj):
|
|
137
|
+
with patch('ae.pythonanywhere.PythonanywhereApi._request', return_value=Mock(status_code=404)):
|
|
138
|
+
api_obj.error_message = 'simulate folder not found 404 error'
|
|
139
|
+
assert api_obj._folder_items('any_folder_path') is None
|
|
140
|
+
assert not api_obj.error_message # 404 error gets reset
|
|
141
|
+
|
|
142
|
+
def test__folder_items_err_empty_folder(self, api_obj):
|
|
143
|
+
with patch('ae.pythonanywhere.PythonanywhereApi._request', return_value=Mock(status_code=200, json=lambda: {})):
|
|
144
|
+
assert api_obj._folder_items('any_folder_path') == []
|
|
145
|
+
assert not api_obj.error_message
|
|
146
|
+
|
|
147
|
+
def test__from_json_err(self, api_obj):
|
|
148
|
+
assert api_obj._from_json(Mock(json=lambda: 1 / 0, content='err-content')) is None
|
|
149
|
+
assert 'err-content' in api_obj.error_message
|
|
150
|
+
|
|
151
|
+
def test_available_consoles(self, api_obj):
|
|
152
|
+
response_mock = Mock(json=lambda: [{'console-name': 'any-type'}])
|
|
153
|
+
with patch('ae.pythonanywhere.PythonanywhereApi._request', return_value=response_mock):
|
|
154
|
+
ret = api_obj.available_consoles()
|
|
155
|
+
assert isinstance(ret, list) and len(ret) == 1
|
|
156
|
+
assert ret[0]['console-name'] == 'any-type'
|
|
157
|
+
assert not api_obj.error_message
|
|
158
|
+
|
|
159
|
+
def test_available_consoles_err(self, api_obj):
|
|
160
|
+
response_mock = Mock(json=lambda: None)
|
|
161
|
+
with patch('ae.pythonanywhere.PythonanywhereApi._request', return_value=response_mock):
|
|
162
|
+
ret = api_obj.available_consoles()
|
|
163
|
+
assert ret == []
|
|
164
|
+
|
|
165
|
+
def test_console_execute(self, api_obj):
|
|
166
|
+
response_mock = Mock(json=lambda: {'output': 'out-put-str'})
|
|
167
|
+
with patch('ae.pythonanywhere.PythonanywhereApi._request', return_value=response_mock):
|
|
168
|
+
ret = api_obj.console_execute(699, 'command-str')
|
|
169
|
+
assert ret == 'out-put-str'
|
|
170
|
+
assert not api_obj.error_message
|
|
171
|
+
|
|
172
|
+
def test_console_execute_err(self, api_obj):
|
|
173
|
+
api_obj.error_message = 'con_exe_err-message'
|
|
174
|
+
with patch('ae.pythonanywhere.PythonanywhereApi._request', return_value=Mock()):
|
|
175
|
+
ret = api_obj.console_execute(699, 'command-str')
|
|
176
|
+
assert ret == ""
|
|
177
|
+
assert api_obj.error_message
|
|
178
|
+
|
|
179
|
+
def test_deployed_code_files(self, api_obj):
|
|
180
|
+
with patch('ae.pythonanywhere.PythonanywhereApi._request',
|
|
181
|
+
return_value=Mock(json=lambda: {'file-Name': {'type': 'any.type'}})):
|
|
182
|
+
ret = api_obj.deployed_code_files('folder-path/*.py')
|
|
183
|
+
assert ret == {'file-Name'}
|
|
184
|
+
|
|
185
|
+
def test_deployed_code_files_err(self, api_obj):
|
|
186
|
+
with patch('ae.pythonanywhere.PythonanywhereApi.find_project_files', return_value=None):
|
|
187
|
+
ret = api_obj.deployed_code_files('folder-path/*.py')
|
|
188
|
+
assert ret is None
|
|
189
|
+
|
|
190
|
+
def test_deployed_file_content(self, api_obj):
|
|
191
|
+
with patch('ae.pythonanywhere.PythonanywhereApi._request', return_value=Mock(content=b'content-str')):
|
|
192
|
+
ret = api_obj.deployed_file_content('folder-path/file.path.xxx')
|
|
193
|
+
assert ret == b'content-str'
|
|
194
|
+
|
|
195
|
+
def test_deployed_file_content_err(self, api_obj):
|
|
196
|
+
api_obj.error_message = 'dep_fil_content-err-message'
|
|
197
|
+
with patch('ae.pythonanywhere.PythonanywhereApi._request', return_value=Mock(content=b'content-str')):
|
|
198
|
+
ret = api_obj.deployed_file_content('folder-path/file.path.xxx')
|
|
199
|
+
assert ret is None
|
|
200
|
+
|
|
201
|
+
def test_deploy_file(self, api_obj):
|
|
202
|
+
with patch('ae.pythonanywhere.PythonanywhereApi._request', return_value=Mock()):
|
|
203
|
+
ret = api_obj.deploy_file('folder-path/file.path.xxx', b'file-content')
|
|
204
|
+
assert ret is api_obj.error_message
|
|
205
|
+
|
|
206
|
+
def test_delete_file_or_folder(self, api_obj):
|
|
207
|
+
with patch('ae.pythonanywhere.PythonanywhereApi._request', return_value=Mock()):
|
|
208
|
+
ret = api_obj.delete_file_or_folder('folder-path/file.path.xxx')
|
|
209
|
+
assert ret is api_obj.error_message
|
|
210
|
+
|
|
211
|
+
|
|
99
212
|
@skip_gitlab_ci # skip on gitlab because of missing remote repository user account token
|
|
100
|
-
class
|
|
213
|
+
class TestIntegrationRunningOnlyLocally:
|
|
101
214
|
def test_init_and_clean_up_from_last_failed_test_run(self, connection):
|
|
102
215
|
assert connection.error_message == ""
|
|
103
216
|
|
|
@@ -110,19 +223,18 @@ class TestHostRunningOnlyLocally:
|
|
|
110
223
|
assert connection.error_message == ""
|
|
111
224
|
assert isinstance(consoles, list)
|
|
112
225
|
|
|
113
|
-
def
|
|
226
|
+
def test_deployed_file_content(self, con_pkg):
|
|
114
227
|
con_pkg.error_message = "" # clear con_pkg instance error from last test method
|
|
115
228
|
|
|
116
229
|
assert con_pkg.deployed_file_content(pkg0_ini_path) == pkg0_ini_content
|
|
117
|
-
assert con_pkg.error_message == ""
|
|
118
230
|
|
|
119
|
-
assert con_pkg.deployed_version() == pkg0_version
|
|
120
231
|
assert con_pkg.error_message == ""
|
|
121
232
|
|
|
122
233
|
inv_fil_path = "not/existing/file_path"
|
|
234
|
+
|
|
123
235
|
assert con_pkg.deployed_file_content(inv_fil_path) is None
|
|
124
|
-
assert inv_fil_path in con_pkg.error_message
|
|
125
236
|
|
|
237
|
+
assert inv_fil_path in con_pkg.error_message
|
|
126
238
|
con_pkg.error_message = "" # clear con_pkg instance error
|
|
127
239
|
|
|
128
240
|
def test_files_iterator_absolute_path(self, con_pkg):
|
|
@@ -293,12 +405,12 @@ class TestHostRunningOnlyLocally:
|
|
|
293
405
|
|
|
294
406
|
|
|
295
407
|
@skip_gitlab_ci # skip on gitlab because of missing remote repository user account token
|
|
296
|
-
class
|
|
408
|
+
class TestIntegrationRunningOnlyLocallyWithPatchedSkipper:
|
|
297
409
|
# with con_pkg.skip_enter_folder patched by deployed_code_file() or find_project_files()
|
|
298
410
|
def test_deployed_code_files(self, con_pkg):
|
|
299
411
|
con_pkg.error_message = "" # clear con_pkg instance error from last test method
|
|
300
412
|
|
|
301
|
-
assert con_pkg.deployed_code_files({os.path.join(
|
|
413
|
+
assert con_pkg.deployed_code_files({os.path.join(TST_PROJECT_NAME, '**', '*.py')}) == {pkg0_ini_path}
|
|
302
414
|
assert con_pkg.error_message == ""
|
|
303
415
|
|
|
304
416
|
found_paths = con_pkg.deployed_code_files(['*/**/media*/*'])
|
|
@@ -322,7 +434,7 @@ class TestHostRunningOnlyLocallyWithPatchedSkipper:
|
|
|
322
434
|
assert found_paths == {pkg0_static_file, pkg2_static_file} # static_ini_file get excluded
|
|
323
435
|
|
|
324
436
|
found_paths = con_pkg.deployed_code_files(['**/static/*'],
|
|
325
|
-
skip_file_path=lambda _: _.startswith(f'{
|
|
437
|
+
skip_file_path=lambda _: _.startswith(f'{TST_PROJECT_NAME}/static/'))
|
|
326
438
|
assert con_pkg.error_message == ""
|
|
327
439
|
assert found_paths == {static_ini_file, pkg2_static_file} # pkg0_static_file get excluded
|
|
328
440
|
|
|
File without changes
|
{ae_pythonanywhere-0.3.1 → ae_pythonanywhere-0.3.3}/ae_pythonanywhere.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{ae_pythonanywhere-0.3.1 → ae_pythonanywhere-0.3.3}/ae_pythonanywhere.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|