arvados-python-client 2.7.4__tar.gz → 3.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. {arvados-python-client-2.7.4/arvados_python_client.egg-info → arvados-python-client-3.0.0}/PKG-INFO +34 -14
  2. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/README.rst +31 -12
  3. arvados-python-client-3.0.0/arvados/__init__.py +69 -0
  4. arvados-python-client-3.0.0/arvados/_internal/__init__.py +83 -0
  5. arvados-python-client-3.0.0/arvados/_internal/basedirs.py +186 -0
  6. {arvados-python-client-2.7.4/arvados → arvados-python-client-3.0.0/arvados/_internal}/diskcache.py +1 -1
  7. {arvados-python-client-2.7.4/arvados → arvados-python-client-3.0.0/arvados/_internal}/http_to_keep.py +11 -14
  8. arvados-python-client-3.0.0/arvados/_internal/report_template.py +114 -0
  9. arvados-python-client-2.7.4/arvados/_ranges.py → arvados-python-client-3.0.0/arvados/_internal/streams.py +82 -22
  10. arvados-python-client-3.0.0/arvados/_version.py +1 -0
  11. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/arvados/api.py +174 -75
  12. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/arvados/arvfile.py +31 -88
  13. arvados-python-client-3.0.0/arvados/cache.py +13 -0
  14. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/arvados/collection.py +22 -490
  15. arvados-python-client-3.0.0/arvados/commands/__init__.py +12 -0
  16. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/arvados/commands/_util.py +0 -22
  17. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/arvados/commands/arv_copy.py +43 -84
  18. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/arvados/commands/keepdocker.py +12 -3
  19. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/arvados/commands/ls.py +0 -3
  20. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/arvados/commands/put.py +28 -21
  21. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/arvados/commands/run.py +0 -5
  22. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/arvados/commands/ws.py +5 -5
  23. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/arvados/config.py +26 -5
  24. arvados-python-client-3.0.0/arvados/events.py +557 -0
  25. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/arvados/keep.py +56 -95
  26. arvados-python-client-3.0.0/arvados/safeapi.py +13 -0
  27. arvados-python-client-3.0.0/arvados/util.py +380 -0
  28. arvados-python-client-3.0.0/arvados-v1-discovery.json +5046 -0
  29. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0/arvados_python_client.egg-info}/PKG-INFO +34 -14
  30. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/arvados_python_client.egg-info/SOURCES.txt +13 -16
  31. arvados-python-client-3.0.0/arvados_python_client.egg-info/requires.txt +7 -0
  32. arvados-python-client-3.0.0/arvados_version.py +140 -0
  33. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/discovery2pydoc.py +133 -66
  34. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/setup.py +9 -25
  35. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/tests/arvados_testutil.py +5 -51
  36. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/tests/keepstub.py +0 -6
  37. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/tests/manifest_examples.py +4 -6
  38. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/tests/performance/test_a_sample.py +0 -3
  39. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/tests/run_test_server.py +63 -74
  40. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/tests/test_api.py +68 -28
  41. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/tests/test_arv_copy.py +71 -1
  42. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/tests/test_arv_get.py +3 -4
  43. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/tests/test_arv_keepdocker.py +19 -8
  44. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/tests/test_arv_ls.py +4 -7
  45. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/tests/test_arv_put.py +80 -10
  46. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/tests/test_arv_ws.py +0 -1
  47. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/tests/test_arvfile.py +83 -24
  48. arvados-python-client-3.0.0/tests/test_basedirs.py +188 -0
  49. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/tests/test_benchmark_collections.py +0 -1
  50. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/tests/test_cmd_util.py +1 -3
  51. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/tests/test_collections.py +134 -514
  52. arvados-python-client-3.0.0/tests/test_computed_permissions.py +78 -0
  53. arvados-python-client-3.0.0/tests/test_config.py +58 -0
  54. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/tests/test_errors.py +0 -1
  55. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/tests/test_events.py +165 -72
  56. arvados-python-client-2.7.4/tests/test_cache.py → arvados-python-client-3.0.0/tests/test_http_cache.py +30 -23
  57. arvados-python-client-2.7.4/tests/test_http.py → arvados-python-client-3.0.0/tests/test_http_to_keep.py +13 -17
  58. arvados-python-client-3.0.0/tests/test_internal.py +35 -0
  59. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/tests/test_keep_client.py +52 -64
  60. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/tests/test_keep_locator.py +0 -4
  61. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/tests/test_retry.py +2 -4
  62. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/tests/test_retry_job_helpers.py +7 -27
  63. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/tests/test_stream.py +9 -76
  64. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/tests/test_util.py +26 -46
  65. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/tests/test_vocabulary.py +2 -1
  66. arvados-python-client-2.7.4/arvados/__init__.py +0 -190
  67. arvados-python-client-2.7.4/arvados/_normalize_stream.py +0 -65
  68. arvados-python-client-2.7.4/arvados/_version.py +0 -1
  69. arvados-python-client-2.7.4/arvados/cache.py +0 -76
  70. arvados-python-client-2.7.4/arvados/commands/migrate19.py +0 -289
  71. arvados-python-client-2.7.4/arvados/crunch.py +0 -34
  72. arvados-python-client-2.7.4/arvados/events.py +0 -342
  73. arvados-python-client-2.7.4/arvados/safeapi.py +0 -81
  74. arvados-python-client-2.7.4/arvados/stream.py +0 -109
  75. arvados-python-client-2.7.4/arvados/timer.py +0 -22
  76. arvados-python-client-2.7.4/arvados/util.py +0 -735
  77. arvados-python-client-2.7.4/arvados-v1-discovery.json +0 -11302
  78. arvados-python-client-2.7.4/arvados_python_client.egg-info/requires.txt +0 -19
  79. arvados-python-client-2.7.4/arvados_version.py +0 -61
  80. arvados-python-client-2.7.4/bin/arv-migrate-docker19 +0 -7
  81. arvados-python-client-2.7.4/tests/performance/__init__.py +0 -0
  82. arvados-python-client-2.7.4/tests/slow_test.py +0 -11
  83. arvados-python-client-2.7.4/tests/test_crunch.py +0 -31
  84. arvados-python-client-2.7.4/tests/test_safeapi.py +0 -63
  85. arvados-python-client-2.7.4/tests/test_sdk.py +0 -47
  86. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/LICENSE-2.0.txt +0 -0
  87. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/MANIFEST.in +0 -0
  88. /arvados-python-client-2.7.4/arvados/_pycurlhelper.py → /arvados-python-client-3.0.0/arvados/_internal/pycurl.py +0 -0
  89. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/arvados/commands/federation_migrate.py +0 -0
  90. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/arvados/commands/get.py +0 -0
  91. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/arvados/errors.py +0 -0
  92. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/arvados/logging.py +0 -0
  93. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/arvados/retry.py +0 -0
  94. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/arvados/vocabulary.py +0 -0
  95. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/arvados_python_client.egg-info/dependency_links.txt +0 -0
  96. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/arvados_python_client.egg-info/not-zip-safe +0 -0
  97. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/arvados_python_client.egg-info/top_level.txt +0 -0
  98. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/bin/arv-copy +0 -0
  99. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/bin/arv-federation-migrate +0 -0
  100. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/bin/arv-get +0 -0
  101. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/bin/arv-keepdocker +0 -0
  102. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/bin/arv-ls +0 -0
  103. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/bin/arv-normalize +0 -0
  104. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/bin/arv-put +0 -0
  105. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/bin/arv-ws +0 -0
  106. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/setup.cfg +0 -0
  107. {arvados-python-client-2.7.4/arvados/commands → arvados-python-client-3.0.0/tests}/__init__.py +0 -0
  108. {arvados-python-client-2.7.4/tests → arvados-python-client-3.0.0/tests/performance}/__init__.py +0 -0
  109. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/tests/performance/performance_profiler.py +0 -0
  110. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/tests/test_arv_normalize.py +0 -0
  111. {arvados-python-client-2.7.4 → arvados-python-client-3.0.0}/tests/test_storage_classes.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 1.1
1
+ Metadata-Version: 1.2
2
2
  Name: arvados-python-client
3
- Version: 2.7.4
3
+ Version: 3.0.0
4
4
  Summary: Arvados client library
5
5
  Home-page: https://arvados.org
6
6
  Author: Arvados
@@ -55,24 +55,43 @@ Description: .. Copyright (C) The Arvados Authors. All rights reserved.
55
55
 
56
56
  arv-get --version
57
57
 
58
- Installing on Debian systems
59
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
60
-
61
- 1. Add this Arvados repository to your sources list::
62
-
63
- deb http://apt.arvados.org/ buster main
64
-
65
- 2. Update your package list.
66
-
67
- 3. Install the ``python3-arvados-python-client`` package.
58
+ Installing on Debian and Ubuntu systems
59
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
60
+
61
+ Arvados publishes packages for Debian 11 "bullseye," Debian 12 "bookworm," Ubuntu 20.04 "focal," and Ubuntu 22.04 "jammy." You can install the Python SDK package on any of these distributions by running the following commands::
62
+
63
+ sudo install -d /etc/apt/keyrings
64
+ sudo curl -fsSL -o /etc/apt/keyrings/arvados.asc https://apt.arvados.org/pubkey.gpg
65
+ sudo tee /etc/apt/sources.list.d/arvados.sources >/dev/null <<EOF
66
+ Types: deb
67
+ URIs: https://apt.arvados.org/$(lsb_release -cs)
68
+ Suites: $(lsb_release -cs)
69
+ Components: main
70
+ Signed-by: /etc/apt/keyrings/arvados.asc
71
+ EOF
72
+ sudo apt update
73
+ sudo apt install python3-arvados-python-client
74
+
75
+ Installing on Red Hat, AlmaLinux, and Rocky Linux
76
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
77
+
78
+ Arvados publishes packages for RHEL 8 and distributions based on it. Note that these packages depend on, and will automatically enable, the Python 3.9 module. You can install the Python SDK package on any of these distributions by running the following commands::
79
+
80
+ sudo tee /etc/yum.repos.d/arvados.repo >/dev/null <<'EOF'
81
+ [arvados]
82
+ name=Arvados
83
+ baseurl=http://rpm.arvados.org/RHEL/$releasever/os/$basearch/
84
+ gpgcheck=1
85
+ gpgkey=http://rpm.arvados.org/RHEL/RPM-GPG-KEY-arvados
86
+ EOF
87
+ sudo dnf install python3-arvados-python-client
68
88
 
69
89
  Configuration
70
90
  -------------
71
91
 
72
92
  This client software needs two pieces of information to connect to
73
93
  Arvados: the DNS name of the API server, and an API authorization
74
- token. You can set these in environment variables, or the file
75
- ``$HOME/.config/arvados/settings.conf``. `The Arvados user
94
+ token. `The Arvados user
76
95
  documentation
77
96
  <http://doc.arvados.org/user/reference/api-tokens.html>`_ describes
78
97
  how to find this information in the Arvados Workbench, and install it
@@ -89,3 +108,4 @@ Description: .. Copyright (C) The Arvados Authors. All rights reserved.
89
108
 
90
109
  Platform: UNKNOWN
91
110
  Classifier: Programming Language :: Python :: 3
111
+ Requires-Python: ~=3.8
@@ -46,24 +46,43 @@ You can test the change by running::
46
46
 
47
47
  arv-get --version
48
48
 
49
- Installing on Debian systems
50
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
51
-
52
- 1. Add this Arvados repository to your sources list::
53
-
54
- deb http://apt.arvados.org/ buster main
55
-
56
- 2. Update your package list.
57
-
58
- 3. Install the ``python3-arvados-python-client`` package.
49
+ Installing on Debian and Ubuntu systems
50
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
51
+
52
+ Arvados publishes packages for Debian 11 "bullseye," Debian 12 "bookworm," Ubuntu 20.04 "focal," and Ubuntu 22.04 "jammy." You can install the Python SDK package on any of these distributions by running the following commands::
53
+
54
+ sudo install -d /etc/apt/keyrings
55
+ sudo curl -fsSL -o /etc/apt/keyrings/arvados.asc https://apt.arvados.org/pubkey.gpg
56
+ sudo tee /etc/apt/sources.list.d/arvados.sources >/dev/null <<EOF
57
+ Types: deb
58
+ URIs: https://apt.arvados.org/$(lsb_release -cs)
59
+ Suites: $(lsb_release -cs)
60
+ Components: main
61
+ Signed-by: /etc/apt/keyrings/arvados.asc
62
+ EOF
63
+ sudo apt update
64
+ sudo apt install python3-arvados-python-client
65
+
66
+ Installing on Red Hat, AlmaLinux, and Rocky Linux
67
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
68
+
69
+ Arvados publishes packages for RHEL 8 and distributions based on it. Note that these packages depend on, and will automatically enable, the Python 3.9 module. You can install the Python SDK package on any of these distributions by running the following commands::
70
+
71
+ sudo tee /etc/yum.repos.d/arvados.repo >/dev/null <<'EOF'
72
+ [arvados]
73
+ name=Arvados
74
+ baseurl=http://rpm.arvados.org/RHEL/$releasever/os/$basearch/
75
+ gpgcheck=1
76
+ gpgkey=http://rpm.arvados.org/RHEL/RPM-GPG-KEY-arvados
77
+ EOF
78
+ sudo dnf install python3-arvados-python-client
59
79
 
60
80
  Configuration
61
81
  -------------
62
82
 
63
83
  This client software needs two pieces of information to connect to
64
84
  Arvados: the DNS name of the API server, and an API authorization
65
- token. You can set these in environment variables, or the file
66
- ``$HOME/.config/arvados/settings.conf``. `The Arvados user
85
+ token. `The Arvados user
67
86
  documentation
68
87
  <http://doc.arvados.org/user/reference/api-tokens.html>`_ describes
69
88
  how to find this information in the Arvados Workbench, and install it
@@ -0,0 +1,69 @@
1
+ # Copyright (C) The Arvados Authors. All rights reserved.
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+ """Arvados Python SDK
5
+
6
+ This module provides the entire Python SDK for Arvados. The most useful modules
7
+ include:
8
+
9
+ * arvados.api - This module provides the `arvados.api.api` function to
10
+ construct an Arvados REST API client, as well as other classes and functions
11
+ that support it. You can call the `arvados.api` module just like a function
12
+ as a shortcut for calling `arvados.api.api`.
13
+
14
+ * arvados.api_resources - The methods on an Arvados REST API client are
15
+ generated dynamically at runtime. This module documents those methods and
16
+ return values for the current version of Arvados. This module does not
17
+ implement anything so you don't need to import it, but it's a helpful
18
+ reference to understand how to use the Arvados REST API client.
19
+
20
+ * arvados.collection - The `arvados.collection.Collection` class provides a
21
+ high-level interface to read and write collections. It coordinates sending
22
+ data to and from Keep, and synchronizing updates with the collection object.
23
+
24
+ * arvados.util - Utility functions to use mostly in conjunction with the API
25
+ client object and the results it returns.
26
+
27
+ Other submodules provide lower-level functionality.
28
+ """
29
+
30
+ import logging as stdliblog
31
+ import os
32
+ import sys
33
+ import types
34
+
35
+ from collections import UserDict
36
+
37
+ from . import api, errors, util
38
+ from .api import api_from_config, http_cache
39
+ from .collection import CollectionReader
40
+ from arvados.keep import *
41
+ from .logging import log_format, log_date_format, log_handler
42
+ from .retry import RetryLoop
43
+
44
+ # Backwards compatibility shims: these modules used to get pulled in after
45
+ # `import arvados` with previous versions of the SDK. We must keep the names
46
+ # accessible even though there's no longer any functional need for them.
47
+ from . import cache
48
+ from . import safeapi
49
+
50
+ # Previous versions of the PySDK used to say `from .api import api`. This
51
+ # made it convenient to call the API client constructor, but difficult to
52
+ # access the rest of the `arvados.api` module. The magic below fixes that
53
+ # bug while retaining backwards compatibility: `arvados.api` is now the
54
+ # module and you can import it normally, but we make that module callable so
55
+ # all the existing code that says `arvados.api('v1', ...)` still works.
56
+ class _CallableAPIModule(api.__class__):
57
+ __call__ = staticmethod(api.api)
58
+ api.__class__ = _CallableAPIModule
59
+
60
+ # Override logging module pulled in via `from ... import *`
61
+ # so users can `import arvados.logging`.
62
+ logging = sys.modules['arvados.logging']
63
+
64
+ # Set up Arvados logging based on the user's configuration.
65
+ # All Arvados code should log under the arvados hierarchy.
66
+ logger = stdliblog.getLogger('arvados')
67
+ logger.addHandler(log_handler)
68
+ logger.setLevel(stdliblog.DEBUG if config.get('ARVADOS_DEBUG')
69
+ else stdliblog.WARNING)
@@ -0,0 +1,83 @@
1
+ # Copyright (C) The Arvados Authors. All rights reserved.
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+ """Arvados internal utilities
5
+
6
+ Everything in `arvados._internal` is support code for the Arvados Python SDK
7
+ and tools. Nothing in this module is intended to be part of the public-facing
8
+ SDK API. Classes and functions in this module may be changed or removed at any
9
+ time.
10
+ """
11
+
12
+ import functools
13
+ import re
14
+ import time
15
+ import warnings
16
+
17
+ class Timer:
18
+ def __init__(self, verbose=False):
19
+ self.verbose = verbose
20
+
21
+ def __enter__(self):
22
+ self.start = time.time()
23
+ return self
24
+
25
+ def __exit__(self, *args):
26
+ self.end = time.time()
27
+ self.secs = self.end - self.start
28
+ self.msecs = self.secs * 1000 # millisecs
29
+ if self.verbose:
30
+ print('elapsed time: %f ms' % self.msecs)
31
+
32
+
33
+ def deprecated(version=None, preferred=None):
34
+ """Mark a callable as deprecated in the SDK
35
+
36
+ This will wrap the callable to emit as a DeprecationWarning
37
+ and add a deprecation notice to its docstring.
38
+
39
+ If the following arguments are given, they'll be included in the
40
+ notices:
41
+
42
+ * preferred: str | None --- The name of an alternative that users should
43
+ use instead.
44
+
45
+ * version: str | None --- The version of Arvados when the callable is
46
+ scheduled to be removed.
47
+ """
48
+ if version is None:
49
+ version = ''
50
+ else:
51
+ version = f' and scheduled to be removed in Arvados {version}'
52
+ if preferred is None:
53
+ preferred = ''
54
+ else:
55
+ preferred = f' Prefer {preferred} instead.'
56
+ def deprecated_decorator(func):
57
+ fullname = f'{func.__module__}.{func.__qualname__}'
58
+ parent, _, name = fullname.rpartition('.')
59
+ if name == '__init__':
60
+ fullname = parent
61
+ warning_msg = f'{fullname} is deprecated{version}.{preferred}'
62
+ @functools.wraps(func)
63
+ def deprecated_wrapper(*args, **kwargs):
64
+ warnings.warn(warning_msg, DeprecationWarning, 2)
65
+ return func(*args, **kwargs)
66
+ # Get func's docstring without any trailing newline or empty lines.
67
+ func_doc = re.sub(r'\n\s*$', '', func.__doc__ or '')
68
+ match = re.search(r'\n([ \t]+)\S', func_doc)
69
+ indent = '' if match is None else match.group(1)
70
+ warning_doc = f'\n\n{indent}.. WARNING:: Deprecated\n{indent} {warning_msg}'
71
+ # Make the deprecation notice the second "paragraph" of the
72
+ # docstring if possible. Otherwise append it.
73
+ docstring, count = re.subn(
74
+ rf'\n[ \t]*\n{indent}',
75
+ f'{warning_doc}\n\n{indent}',
76
+ func_doc,
77
+ count=1,
78
+ )
79
+ if not count:
80
+ docstring = f'{func_doc.lstrip()}{warning_doc}'
81
+ deprecated_wrapper.__doc__ = docstring
82
+ return deprecated_wrapper
83
+ return deprecated_decorator
@@ -0,0 +1,186 @@
1
+ # Copyright (C) The Arvados Authors. All rights reserved.
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+ """Base directories utility module
5
+
6
+ This module provides a set of classes useful to search and manipulate base
7
+ directory defined by systemd and the XDG specification. Most users will just
8
+ instantiate and use `BaseDirectories`.
9
+ """
10
+
11
+ import dataclasses
12
+ import enum
13
+ import itertools
14
+ import logging
15
+ import os
16
+ import shlex
17
+ import stat
18
+
19
+ from pathlib import Path, PurePath
20
+ from typing import (
21
+ Iterator,
22
+ Mapping,
23
+ Optional,
24
+ Union,
25
+ )
26
+
27
+ logger = logging.getLogger('arvados')
28
+
29
+ @dataclasses.dataclass
30
+ class BaseDirectorySpec:
31
+ """Parse base directories
32
+
33
+ A BaseDirectorySpec defines all the environment variable keys and defaults
34
+ related to a set of base directories (cache, config, state, etc.). It
35
+ provides pure methods to parse environment settings into valid paths.
36
+ """
37
+ systemd_key: str
38
+ xdg_home_key: str
39
+ xdg_home_default: PurePath
40
+ xdg_dirs_key: Optional[str] = None
41
+ xdg_dirs_default: str = ''
42
+
43
+ @staticmethod
44
+ def _abspath_from_env(env: Mapping[str, str], key: str) -> Optional[Path]:
45
+ try:
46
+ path = Path(env[key])
47
+ except (KeyError, ValueError):
48
+ ok = False
49
+ else:
50
+ ok = path.is_absolute()
51
+ return path if ok else None
52
+
53
+ @staticmethod
54
+ def _iter_abspaths(value: str) -> Iterator[Path]:
55
+ for path_s in value.split(':'):
56
+ path = Path(path_s)
57
+ if path.is_absolute():
58
+ yield path
59
+
60
+ def iter_systemd(self, env: Mapping[str, str]) -> Iterator[Path]:
61
+ return self._iter_abspaths(env.get(self.systemd_key, ''))
62
+
63
+ def iter_xdg(self, env: Mapping[str, str], subdir: PurePath) -> Iterator[Path]:
64
+ yield self.xdg_home(env, subdir)
65
+ if self.xdg_dirs_key is not None:
66
+ for path in self._iter_abspaths(env.get(self.xdg_dirs_key) or self.xdg_dirs_default):
67
+ yield path / subdir
68
+
69
+ def xdg_home(self, env: Mapping[str, str], subdir: PurePath) -> Path:
70
+ return (
71
+ self._abspath_from_env(env, self.xdg_home_key)
72
+ or self.xdg_home_default_path(env)
73
+ ) / subdir
74
+
75
+ def xdg_home_default_path(self, env: Mapping[str, str]) -> Path:
76
+ return (self._abspath_from_env(env, 'HOME') or Path.home()) / self.xdg_home_default
77
+
78
+ def xdg_home_is_customized(self, env: Mapping[str, str]) -> bool:
79
+ xdg_home = self._abspath_from_env(env, self.xdg_home_key)
80
+ return xdg_home is not None and xdg_home != self.xdg_home_default_path(env)
81
+
82
+
83
+ class BaseDirectorySpecs(enum.Enum):
84
+ """Base directory specifications
85
+
86
+ This enum provides easy access to the standard base directory settings.
87
+ """
88
+ CACHE = BaseDirectorySpec(
89
+ 'CACHE_DIRECTORY',
90
+ 'XDG_CACHE_HOME',
91
+ PurePath('.cache'),
92
+ )
93
+ CONFIG = BaseDirectorySpec(
94
+ 'CONFIGURATION_DIRECTORY',
95
+ 'XDG_CONFIG_HOME',
96
+ PurePath('.config'),
97
+ 'XDG_CONFIG_DIRS',
98
+ '/etc/xdg',
99
+ )
100
+ STATE = BaseDirectorySpec(
101
+ 'STATE_DIRECTORY',
102
+ 'XDG_STATE_HOME',
103
+ PurePath('.local', 'state'),
104
+ )
105
+
106
+
107
+ class BaseDirectories:
108
+ """Resolve paths from a base directory spec
109
+
110
+ Given a BaseDirectorySpec, this class provides stateful methods to find
111
+ existing files and return the most-preferred directory for writing.
112
+ """
113
+ _STORE_MODE = stat.S_IFDIR | stat.S_IWUSR
114
+
115
+ def __init__(
116
+ self,
117
+ spec: Union[BaseDirectorySpec, BaseDirectorySpecs, str],
118
+ env: Mapping[str, str]=os.environ,
119
+ xdg_subdir: Union[os.PathLike, str]='arvados',
120
+ ) -> None:
121
+ if isinstance(spec, str):
122
+ spec = BaseDirectorySpecs[spec].value
123
+ elif isinstance(spec, BaseDirectorySpecs):
124
+ spec = spec.value
125
+ self._spec = spec
126
+ self._env = env
127
+ self._xdg_subdir = PurePath(xdg_subdir)
128
+
129
+ def search(self, name: str) -> Iterator[Path]:
130
+ any_found = False
131
+ for search_path in itertools.chain(
132
+ self._spec.iter_systemd(self._env),
133
+ self._spec.iter_xdg(self._env, self._xdg_subdir),
134
+ ):
135
+ path = search_path / name
136
+ if path.exists():
137
+ yield path
138
+ any_found = True
139
+ # The rest of this function is dedicated to warning the user if they
140
+ # have a custom XDG_*_HOME value that prevented the search from
141
+ # succeeding. This should be rare.
142
+ if any_found or not self._spec.xdg_home_is_customized(self._env):
143
+ return
144
+ default_home = self._spec.xdg_home_default_path(self._env)
145
+ default_path = Path(self._xdg_subdir / name)
146
+ if not (default_home / default_path).exists():
147
+ return
148
+ if self._spec.xdg_dirs_key is None:
149
+ suggest_key = self._spec.xdg_home_key
150
+ suggest_value = default_home
151
+ else:
152
+ suggest_key = self._spec.xdg_dirs_key
153
+ cur_value = self._env.get(suggest_key, '')
154
+ value_sep = ':' if cur_value else ''
155
+ suggest_value = f'{cur_value}{value_sep}{default_home}'
156
+ logger.warning(
157
+ "\
158
+ %s was not found under your configured $%s (%s), \
159
+ but does exist at the default location (%s) - \
160
+ consider running this program with the environment setting %s=%s\
161
+ ",
162
+ default_path,
163
+ self._spec.xdg_home_key,
164
+ self._spec.xdg_home(self._env, ''),
165
+ default_home,
166
+ suggest_key,
167
+ shlex.quote(suggest_value),
168
+ )
169
+
170
+ def storage_path(
171
+ self,
172
+ subdir: Union[str, os.PathLike]=PurePath(),
173
+ mode: int=0o700,
174
+ ) -> Path:
175
+ for path in self._spec.iter_systemd(self._env):
176
+ try:
177
+ mode = path.stat().st_mode
178
+ except OSError:
179
+ continue
180
+ if (mode & self._STORE_MODE) == self._STORE_MODE:
181
+ break
182
+ else:
183
+ path = self._spec.xdg_home(self._env, self._xdg_subdir)
184
+ path /= subdir
185
+ path.mkdir(parents=True, exist_ok=True, mode=mode)
186
+ return path
@@ -39,7 +39,7 @@ class DiskCacheSlot(object):
39
39
  # just a few pages at a time), reducing the number of page
40
40
  # faults and improving performance by 4x compared to not
41
41
  # calling madvise.
42
- if self.content and hasattr(mmap.mmap, 'madvise'):
42
+ if self.content:
43
43
  self.content.madvise(mmap.MADV_WILLNEED)
44
44
  return self.content
45
45
 
@@ -2,24 +2,21 @@
2
2
  #
3
3
  # SPDX-License-Identifier: Apache-2.0
4
4
 
5
- from __future__ import division
6
- from future import standard_library
7
- standard_library.install_aliases()
8
-
9
- import email.utils
10
- import time
5
+ import calendar
6
+ import dataclasses
11
7
  import datetime
12
- import re
13
- import arvados
14
- import arvados.collection
15
- import urllib.parse
8
+ import email.utils
16
9
  import logging
17
- import calendar
10
+ import re
11
+ import time
12
+ import typing
18
13
  import urllib.parse
14
+
19
15
  import pycurl
20
- import dataclasses
21
- import typing
22
- from arvados._pycurlhelper import PyCurlHelper
16
+
17
+ import arvados
18
+ import arvados.collection
19
+ from .pycurl import PyCurlHelper
23
20
 
24
21
  logger = logging.getLogger('arvados.http_import')
25
22
 
@@ -0,0 +1,114 @@
1
+ # Copyright (C) The Arvados Authors. All rights reserved.
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ try:
6
+ from html import escape
7
+ except ImportError:
8
+ from cgi import escape
9
+
10
+ import json
11
+ from typing import ItemsView
12
+
13
+ class ReportTemplate(object):
14
+ """Base class for HTML reports produced by Arvados reporting tools.
15
+
16
+ Used by crunchstat-summary and cluster-activity.
17
+
18
+ """
19
+
20
+ STYLE = '''
21
+ <style>
22
+ body {
23
+ background: #fafafa;
24
+ font-family: "Roboto", "Helvetica", "Arial", sans-serif;
25
+ font-size: 0.875rem;
26
+ color: rgba(0, 0, 0, 0.87);
27
+ font-weight: 400;
28
+ }
29
+ .card {
30
+ background: #ffffff;
31
+ box-shadow: 0px 1px 5px 0px rgba(0,0,0,0.2),0px 2px 2px 0px rgba(0,0,0,0.14),0px 3px 1px -2px rgba(0,0,0,0.12);
32
+ border-radius: 4px;
33
+ margin: 20px;
34
+ }
35
+ .content {
36
+ padding: 2px 16px 8px 16px;
37
+ }
38
+ table {
39
+ border-spacing: 0px;
40
+ }
41
+ tr {
42
+ height: 36px;
43
+ text-align: left;
44
+ }
45
+ th {
46
+ padding-right: 4em;
47
+ border-top: 1px solid rgba(224, 224, 224, 1);
48
+ }
49
+ td {
50
+ padding-right: 2em;
51
+ border-top: 1px solid rgba(224, 224, 224, 1);
52
+ }
53
+ #chart {
54
+ margin-left: -20px;
55
+ }
56
+ </style>
57
+ '''
58
+
59
+ def __init__(self, label):
60
+ self.label = label
61
+ self.cards = []
62
+
63
+ def cardlist(self, items):
64
+ if not isinstance(items, list):
65
+ items = [items]
66
+
67
+ return "\n".join(
68
+ """
69
+ <div class="card">
70
+ <div class="content">
71
+ {}
72
+ </div>
73
+ </div>""".format(i) for i in items)
74
+
75
+ def html(self):
76
+ return '''<!doctype html>
77
+ <html>
78
+ <head>
79
+ <title>{label}</title>
80
+
81
+ {js}
82
+
83
+ {style}
84
+
85
+ {header}
86
+
87
+ </head>
88
+
89
+ <body>
90
+ <div class="card">
91
+ <div class="content">
92
+ <h1>{label}</h1>
93
+ </div>
94
+ </div>
95
+
96
+ {cards}
97
+
98
+ </body>
99
+ </html>
100
+ '''.format(label=escape(self.label),
101
+ js=self.js(),
102
+ style=self.style(),
103
+ header=self.headHTML(),
104
+ cards=self.cardlist(self.cards))
105
+
106
+ def js(self):
107
+ return ''
108
+
109
+ def style(self):
110
+ return self.STYLE
111
+
112
+ def headHTML(self):
113
+ """Return extra HTML text to include in HEAD."""
114
+ return ''