python-alfresco-api 1.1.0__py3-none-any.whl → 1.1.2__py3-none-any.whl

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 (64) hide show
  1. python_alfresco_api/__init__.py +8 -2
  2. python_alfresco_api/auth_util.py +39 -8
  3. python_alfresco_api/client_factory.py +46 -10
  4. python_alfresco_api/clients/__init__.py +1 -1
  5. python_alfresco_api/clients/auth/__init__.py +5 -2
  6. python_alfresco_api/clients/auth/auth_client.py +13 -6
  7. python_alfresco_api/clients/auth/authentication/__init__.py +2 -1
  8. python_alfresco_api/clients/core/__init__.py +14 -1
  9. python_alfresco_api/clients/core/actions/__init__.py +2 -1
  10. python_alfresco_api/clients/core/activities/__init__.py +2 -1
  11. python_alfresco_api/clients/core/audit/__init__.py +2 -1
  12. python_alfresco_api/clients/core/comments/__init__.py +2 -1
  13. python_alfresco_api/clients/core/content/__init__.py +2 -1
  14. python_alfresco_api/clients/core/core_client.py +26 -8
  15. python_alfresco_api/clients/core/downloads/__init__.py +11 -0
  16. python_alfresco_api/clients/core/downloads/downloads_client.py +190 -0
  17. python_alfresco_api/clients/core/downloads/models.py +84 -0
  18. python_alfresco_api/clients/core/favorites/__init__.py +2 -1
  19. python_alfresco_api/clients/core/groups/__init__.py +2 -1
  20. python_alfresco_api/clients/core/networks/__init__.py +2 -1
  21. python_alfresco_api/clients/core/nodes/__init__.py +30 -1
  22. python_alfresco_api/clients/core/people/__init__.py +2 -1
  23. python_alfresco_api/clients/core/preferences/__init__.py +2 -1
  24. python_alfresco_api/clients/core/probes/__init__.py +2 -1
  25. python_alfresco_api/clients/core/queries/__init__.py +2 -1
  26. python_alfresco_api/clients/core/ratings/__init__.py +2 -1
  27. python_alfresco_api/clients/core/renditions/__init__.py +3 -2
  28. python_alfresco_api/clients/core/shared_links/__init__.py +2 -1
  29. python_alfresco_api/clients/core/sites/__init__.py +2 -1
  30. python_alfresco_api/clients/core/tags/__init__.py +2 -1
  31. python_alfresco_api/clients/core/trashcan/__init__.py +2 -1
  32. python_alfresco_api/clients/core/versions/__init__.py +2 -1
  33. python_alfresco_api/clients/discovery/__init__.py +5 -2
  34. python_alfresco_api/clients/discovery/discovery/__init__.py +2 -1
  35. python_alfresco_api/clients/discovery/discovery_client.py +13 -6
  36. python_alfresco_api/clients/model/__init__.py +9 -2
  37. python_alfresco_api/clients/model/aspects/__init__.py +2 -1
  38. python_alfresco_api/clients/model/model_client.py +13 -6
  39. python_alfresco_api/clients/model/types/__init__.py +2 -1
  40. python_alfresco_api/clients/search/__init__.py +9 -2
  41. python_alfresco_api/clients/search/search/__init__.py +2 -1
  42. python_alfresco_api/clients/search/search_client.py +13 -6
  43. python_alfresco_api/clients/search_sql/__init__.py +9 -2
  44. python_alfresco_api/clients/search_sql/search_sql_client.py +13 -6
  45. python_alfresco_api/clients/search_sql/sql/__init__.py +2 -1
  46. python_alfresco_api/clients/search_sql/sql/sql_client.py +3 -2
  47. python_alfresco_api/clients/workflow/__init__.py +9 -2
  48. python_alfresco_api/clients/workflow/deployments/__init__.py +2 -1
  49. python_alfresco_api/clients/workflow/process_definitions/__init__.py +3 -1
  50. python_alfresco_api/clients/workflow/process_definitions/process_definitions_client.py +3 -3
  51. python_alfresco_api/clients/workflow/processes/__init__.py +3 -1
  52. python_alfresco_api/clients/workflow/processes/processes_client.py +53 -53
  53. python_alfresco_api/clients/workflow/tasks/__init__.py +3 -1
  54. python_alfresco_api/clients/workflow/tasks/tasks_client.py +37 -37
  55. python_alfresco_api/clients/workflow/workflow_client.py +21 -7
  56. python_alfresco_api/raw_clients/alfresco_core_client/core_client/api/downloads/__init__.py +1 -0
  57. python_alfresco_api/raw_clients/alfresco_core_client/core_client/api/downloads/cancel_download.py +146 -0
  58. python_alfresco_api/raw_clients/alfresco_core_client/core_client/api/downloads/create_download.py +284 -0
  59. python_alfresco_api/raw_clients/alfresco_core_client/core_client/api/downloads/get_download.py +221 -0
  60. python_alfresco_api/utils/content_utils_highlevel.py +97 -2
  61. {python_alfresco_api-1.1.0.dist-info → python_alfresco_api-1.1.2.dist-info}/METADATA +44 -7
  62. {python_alfresco_api-1.1.0.dist-info → python_alfresco_api-1.1.2.dist-info}/RECORD +64 -57
  63. {python_alfresco_api-1.1.0.dist-info → python_alfresco_api-1.1.2.dist-info}/WHEEL +0 -0
  64. {python_alfresco_api-1.1.0.dist-info → python_alfresco_api-1.1.2.dist-info}/licenses/LICENSE +0 -0
@@ -33,7 +33,10 @@ from .clients.conversion_utils import (
33
33
  create_converter_pair
34
34
  )
35
35
 
36
- __version__ = "1.0.0"
36
+ # Import raw_clients to ensure they get packaged
37
+ from . import raw_clients
38
+
39
+ __version__ = "1.1.1"
37
40
  __all__ = [
38
41
  # Factory & utilities
39
42
  "ClientFactory",
@@ -52,5 +55,8 @@ __all__ = [
52
55
  # Conversion utilities
53
56
  "pydantic_to_attrs_dict",
54
57
  "attrs_to_pydantic",
55
- "create_converter_pair"
58
+ "create_converter_pair",
59
+
60
+ # Raw clients
61
+ "raw_clients"
56
62
  ]
@@ -24,6 +24,7 @@ def load_env_config(
24
24
  username: Optional[str] = None,
25
25
  password: Optional[str] = None,
26
26
  verify_ssl: Optional[Union[bool, str]] = None,
27
+ timeout: Optional[int] = None,
27
28
  load_env: bool = True,
28
29
  env_file: Optional[str] = None
29
30
  ) -> Dict[str, Any]:
@@ -37,6 +38,7 @@ def load_env_config(
37
38
  username: Explicit username (overrides env)
38
39
  password: Explicit password (overrides env)
39
40
  verify_ssl: SSL verification - True/False or path to certificate bundle (overrides env)
41
+ timeout: Request timeout in seconds (overrides env)
40
42
  load_env: Whether to load from environment/.env file
41
43
  env_file: Specific .env file path
42
44
 
@@ -55,6 +57,19 @@ def load_env_config(
55
57
  resolved_username = username or os.getenv('ALFRESCO_USERNAME') or 'admin'
56
58
  resolved_password = password or os.getenv('ALFRESCO_PASSWORD') or 'admin'
57
59
 
60
+ # Handle timeout with environment variable support
61
+ if timeout is not None:
62
+ resolved_timeout = timeout
63
+ else:
64
+ timeout_env = os.getenv('ALFRESCO_TIMEOUT')
65
+ if timeout_env:
66
+ try:
67
+ resolved_timeout = int(timeout_env)
68
+ except ValueError:
69
+ resolved_timeout = None # Invalid value, don't set timeout
70
+ else:
71
+ resolved_timeout = None # No timeout specified, let system/client defaults apply
72
+
58
73
  # Handle SSL verification (supports bool or certificate path like raw client)
59
74
  if verify_ssl is not None:
60
75
  resolved_verify_ssl = verify_ssl
@@ -73,7 +88,8 @@ def load_env_config(
73
88
  'base_url': resolved_base_url,
74
89
  'username': resolved_username,
75
90
  'password': resolved_password,
76
- 'verify_ssl': resolved_verify_ssl
91
+ 'verify_ssl': resolved_verify_ssl,
92
+ 'timeout': resolved_timeout
77
93
  }
78
94
 
79
95
  class SimpleAuthUtil:
@@ -130,7 +146,7 @@ class AuthUtil:
130
146
  username: str,
131
147
  password: str,
132
148
  verify_ssl: Union[bool, str] = True,
133
- timeout: int = 30
149
+ timeout: Optional[int] = None
134
150
  ):
135
151
  """
136
152
  Initialize authentication utility.
@@ -140,7 +156,7 @@ class AuthUtil:
140
156
  username: Alfresco username
141
157
  password: Alfresco password
142
158
  verify_ssl: SSL verification - True, False, or path to certificate bundle
143
- timeout: Request timeout in seconds
159
+ timeout: Request timeout in seconds (None = use system defaults)
144
160
  """
145
161
  self.base_url = base_url.rstrip('/')
146
162
  self.username = username
@@ -167,7 +183,12 @@ class AuthUtil:
167
183
  auth_url = f"{self.base_url}/alfresco/api/-default-/public/authentication/versions/1/tickets"
168
184
  auth_data = {"userId": self.username, "password": self.password}
169
185
 
170
- async with httpx.AsyncClient(verify=self.verify_ssl, timeout=self.timeout) as client:
186
+ # Create httpx client with timeout only if specified
187
+ client_kwargs = {"verify": self.verify_ssl}
188
+ if self.timeout is not None:
189
+ client_kwargs["timeout"] = self.timeout
190
+
191
+ async with httpx.AsyncClient(**client_kwargs) as client:
171
192
  response = await client.post(auth_url, json=auth_data)
172
193
 
173
194
  if response.status_code == 201:
@@ -338,7 +359,7 @@ class OAuth2AuthUtil:
338
359
  refresh_token: Optional[str] = None,
339
360
  # Standard auth util parameters
340
361
  verify_ssl: Union[bool, str] = True,
341
- timeout: int = 30,
362
+ timeout: Optional[int] = None,
342
363
  # Environment loading
343
364
  load_env: bool = True,
344
365
  env_file: Optional[str] = None
@@ -358,7 +379,7 @@ class OAuth2AuthUtil:
358
379
  access_token: Existing access token (optional)
359
380
  refresh_token: Existing refresh token (optional)
360
381
  verify_ssl: SSL verification - True, False, or path to certificate bundle
361
- timeout: Request timeout in seconds
382
+ timeout: Request timeout in seconds (None = use system defaults)
362
383
  load_env: Whether to load configuration from environment
363
384
  env_file: Optional path to .env file
364
385
  """
@@ -477,7 +498,12 @@ class OAuth2AuthUtil:
477
498
  if self.scope:
478
499
  data["scope"] = self.scope
479
500
 
480
- async with httpx.AsyncClient(verify=self.verify_ssl, timeout=self.timeout) as client:
501
+ # Create httpx client with timeout only if specified
502
+ client_kwargs = {"verify": self.verify_ssl}
503
+ if self.timeout is not None:
504
+ client_kwargs["timeout"] = self.timeout
505
+
506
+ async with httpx.AsyncClient(**client_kwargs) as client:
481
507
  response = await client.post(
482
508
  self.token_endpoint,
483
509
  data=data,
@@ -516,7 +542,12 @@ class OAuth2AuthUtil:
516
542
  if self.client_secret:
517
543
  data["client_secret"] = self.client_secret
518
544
 
519
- async with httpx.AsyncClient(verify=self.verify_ssl, timeout=self.timeout) as client:
545
+ # Create httpx client with timeout only if specified
546
+ client_kwargs = {"verify": self.verify_ssl}
547
+ if self.timeout is not None:
548
+ client_kwargs["timeout"] = self.timeout
549
+
550
+ async with httpx.AsyncClient(**client_kwargs) as client:
520
551
  response = await client.post(
521
552
  self.token_endpoint,
522
553
  data=data,
@@ -54,7 +54,7 @@ class ClientFactory:
54
54
  password: Optional[str] = None,
55
55
  auth_util = None, # Pass existing auth_util (any type)
56
56
  verify_ssl: Optional[Union[bool, str]] = None,
57
- timeout: int = 30,
57
+ timeout: Optional[int] = None,
58
58
  load_env: bool = True,
59
59
  env_file: Optional[str] = None
60
60
  ):
@@ -69,8 +69,9 @@ class ClientFactory:
69
69
  username: Username for authentication (overrides env)
70
70
  password: Password for authentication (overrides env)
71
71
  auth_util: Pre-configured auth util (SimpleAuthUtil, AuthUtil, OAuth2AuthUtil, etc.)
72
+ If provided, its parameters (timeout, base_url, verify_ssl) take priority
72
73
  verify_ssl: SSL verification - True, False, or path to certificate bundle (overrides env)
73
- timeout: Request timeout in seconds
74
+ timeout: Request timeout in seconds (overrides env, but auth_util.timeout takes precedence)
74
75
  load_env: Whether to automatically load from environment/env file
75
76
  env_file: Specific .env file path (default: .env in current directory)
76
77
  """
@@ -81,6 +82,7 @@ class ClientFactory:
81
82
  username=username,
82
83
  password=password,
83
84
  verify_ssl=verify_ssl,
85
+ timeout=timeout,
84
86
  load_env=load_env,
85
87
  env_file=env_file
86
88
  )
@@ -88,21 +90,45 @@ class ClientFactory:
88
90
  # Store resolved configuration
89
91
  self._base_url = config['base_url']
90
92
  self.verify_ssl = config['verify_ssl']
91
- self.timeout = timeout
93
+ self.timeout = config['timeout'] # May be None if not specified
92
94
 
93
95
  # Handle authentication centrally - support all patterns
94
96
  if auth_util is not None:
95
97
  # Use provided auth_util (any type: SimpleAuthUtil, AuthUtil, OAuth2AuthUtil)
98
+ # Respect auth_util's existing configuration if it has parameters
96
99
  self.auth = auth_util
100
+
101
+ # If auth_util has its own timeout, use it; otherwise use our resolved timeout
102
+ if hasattr(auth_util, 'timeout') and auth_util.timeout is not None:
103
+ self.timeout = auth_util.timeout
104
+
105
+ # If auth_util has its own base_url, use it; otherwise keep our resolved base_url
106
+ if hasattr(auth_util, 'base_url') and auth_util.base_url:
107
+ self._base_url = auth_util.base_url
108
+
109
+ # If auth_util has its own verify_ssl, use it; otherwise keep our resolved verify_ssl
110
+ if hasattr(auth_util, 'verify_ssl') and auth_util.verify_ssl is not None:
111
+ self.verify_ssl = auth_util.verify_ssl
112
+
113
+ # Store auth_util credentials for access (don't override the auth_util itself)
114
+ self._auth_username = getattr(auth_util, 'username', None)
115
+ self._auth_password = getattr(auth_util, 'password', None)
97
116
  elif config['username'] and config['password']:
98
117
  # Create full AuthUtil with query parameter support (including from env)
99
- self.auth = AuthUtil(
100
- base_url=config['base_url'],
101
- username=config['username'],
102
- password=config['password'],
103
- verify_ssl=config['verify_ssl'],
104
- timeout=timeout
105
- )
118
+ # Only pass timeout if it's specified (not None)
119
+ auth_kwargs = {
120
+ 'base_url': config['base_url'],
121
+ 'username': config['username'],
122
+ 'password': config['password'],
123
+ 'verify_ssl': config['verify_ssl']
124
+ }
125
+ if config['timeout'] is not None:
126
+ auth_kwargs['timeout'] = config['timeout']
127
+
128
+ self.auth = AuthUtil(**auth_kwargs)
129
+ # Store credentials for access
130
+ self._auth_username = config['username']
131
+ self._auth_password = config['password']
106
132
  else:
107
133
  # No authentication available
108
134
  raise ValueError(
@@ -117,6 +143,16 @@ class ClientFactory:
117
143
  """Get the server base URL."""
118
144
  return self._base_url
119
145
 
146
+ @property
147
+ def username(self) -> Optional[str]:
148
+ """Get the authentication username."""
149
+ return getattr(self, '_auth_username', None)
150
+
151
+ @property
152
+ def password(self) -> Optional[str]:
153
+ """Get the authentication password."""
154
+ return getattr(self, '_auth_password', None)
155
+
120
156
  @classmethod
121
157
  def from_env(cls, env_file: Optional[str] = None) -> 'ClientFactory':
122
158
  """
@@ -55,6 +55,6 @@ __all__ = [
55
55
  ]
56
56
 
57
57
  # Module metadata for discovery
58
- __version__ = "1.1.0"
58
+ __version__ = "1.1.1"
59
59
  __description__ = "Alfresco API Clients with three-tier architecture and lazy loading"
60
60
  __author__ = "Python Alfresco API Project"
@@ -10,5 +10,8 @@ from .models import AuthResponse, AuthRequest
10
10
  # Import the main client class
11
11
  from .auth_client import AlfrescoAuthClient
12
12
 
13
- # Export the client class
14
- __all__ = ['AlfrescoAuthClient', 'AuthResponse', 'AuthRequest']
13
+ # Import models module itself to ensure it gets packaged
14
+ from . import models
15
+
16
+ # Export the client class, models, and the models module itself
17
+ __all__ = ['AlfrescoAuthClient', 'AuthResponse', 'AuthRequest', 'models']
@@ -80,12 +80,19 @@ class AlfrescoAuthClient:
80
80
  """
81
81
  from ...raw_clients.alfresco_auth_client.auth_client.client import AuthenticatedClient
82
82
 
83
- return AuthenticatedClient(
84
- base_url=f"{self._client_factory.base_url}/alfresco/api/-default-/public/authentication/versions/1",
85
- token=self._client_factory.auth.get_auth_token(),
86
- prefix=self._client_factory.auth.get_auth_prefix(),
87
- verify_ssl=self._client_factory.verify_ssl
88
- )
83
+ # Prepare client arguments
84
+ client_kwargs = {
85
+ "base_url": f"{self._client_factory.base_url}/alfresco/api/-default-/public/authentication/versions/1",
86
+ "token": self._client_factory.auth.get_auth_token(),
87
+ "prefix": self._client_factory.auth.get_auth_prefix(),
88
+ "verify_ssl": self._client_factory.verify_ssl
89
+ }
90
+
91
+ # Only add timeout if specified (not None)
92
+ if self._client_factory.timeout is not None:
93
+ client_kwargs["timeout"] = self._client_factory.timeout
94
+
95
+ return AuthenticatedClient(**client_kwargs)
89
96
 
90
97
  def _create_httpx_client(self):
91
98
  """
@@ -6,5 +6,6 @@ Part of the three-tier V1.1 architecture with complete 4-pattern detailed functi
6
6
  """
7
7
 
8
8
  from .authentication_client import AuthenticationClient
9
+ from . import models
9
10
 
10
- __all__ = ['AuthenticationClient']
11
+ __all__ = ['AuthenticationClient', 'models']
@@ -8,4 +8,17 @@ and other repository operations through a clean, lazy-loaded interface.
8
8
  # Import the client class from separate file
9
9
  from .core_client import AlfrescoCoreClient
10
10
 
11
- __all__ = ['AlfrescoCoreClient']
11
+ # Import all submodules to ensure they get packaged
12
+ from . import actions, activities, audit, comments, content, downloads
13
+ from . import favorites, groups, networks, nodes, people, preferences
14
+ from . import probes, queries, ratings, renditions, shared_links, sites
15
+ from . import tags, trashcan, versions, models
16
+
17
+ __all__ = [
18
+ 'AlfrescoCoreClient',
19
+ # All lazy-loaded submodules and models
20
+ 'actions', 'activities', 'audit', 'comments', 'content', 'downloads',
21
+ 'favorites', 'groups', 'networks', 'nodes', 'people', 'preferences',
22
+ 'probes', 'queries', 'ratings', 'renditions', 'shared_links', 'sites',
23
+ 'tags', 'trashcan', 'versions', 'models'
24
+ ]
@@ -6,5 +6,6 @@ Part of the three-tier V1.1 architecture with complete 4-pattern detailed functi
6
6
  """
7
7
 
8
8
  from .actions_client import ActionsClient
9
+ from . import models
9
10
 
10
- __all__ = ['ActionsClient']
11
+ __all__ = ['ActionsClient', 'models']
@@ -6,5 +6,6 @@ Part of the three-tier V1.1 architecture with complete 4-pattern detailed functi
6
6
  """
7
7
 
8
8
  from .activities_client import ActivitiesClient
9
+ from . import models
9
10
 
10
- __all__ = ['ActivitiesClient']
11
+ __all__ = ['ActivitiesClient', 'models']
@@ -6,5 +6,6 @@ Part of the three-tier V1.1 architecture with complete 4-pattern detailed functi
6
6
  """
7
7
 
8
8
  from .audit_client import AuditClient
9
+ from . import models
9
10
 
10
- __all__ = ['AuditClient']
11
+ __all__ = ['AuditClient', 'models']
@@ -6,5 +6,6 @@ Part of the three-tier V1.1 architecture with complete 4-pattern detailed functi
6
6
  """
7
7
 
8
8
  from .comments_client import CommentsClient
9
+ from . import models
9
10
 
10
- __all__ = ['CommentsClient']
11
+ __all__ = ['CommentsClient', 'models']
@@ -7,9 +7,10 @@ Part of the three-tier V1.1 architecture.
7
7
 
8
8
  # Import from Level 3 (operation-specific models)
9
9
  from .models import UploadResponse, DownloadResponse
10
+ from . import models
10
11
 
11
12
  # Import the main client class
12
13
  from .content_client import ContentClient
13
14
 
14
15
  # Export the client class and models
15
- __all__ = ['ContentClient', 'UploadResponse', 'DownloadResponse']
16
+ __all__ = ['ContentClient', 'UploadResponse', 'DownloadResponse', 'models']
@@ -138,13 +138,20 @@ class AlfrescoCoreClient:
138
138
  # Import the raw core client directly
139
139
  from ...raw_clients.alfresco_core_client.core_client.client import AuthenticatedClient
140
140
 
141
- # Create the raw client with same auth setup
142
- return AuthenticatedClient(
143
- base_url=f"{self._client_factory.base_url}/alfresco/api/-default-/public/alfresco/versions/1",
144
- token=self._client_factory.auth.get_auth_token(),
145
- prefix=self._client_factory.auth.get_auth_prefix(),
146
- verify_ssl=self._client_factory.verify_ssl
147
- )
141
+ # Prepare client arguments
142
+ client_kwargs = {
143
+ "base_url": f"{self._client_factory.base_url}/alfresco/api/-default-/public/alfresco/versions/1",
144
+ "token": self._client_factory.auth.get_auth_token(),
145
+ "prefix": self._client_factory.auth.get_auth_prefix(),
146
+ "verify_ssl": self._client_factory.verify_ssl
147
+ }
148
+
149
+ # Only add timeout if specified (not None)
150
+ if self._client_factory.timeout is not None:
151
+ client_kwargs["timeout"] = self._client_factory.timeout
152
+
153
+ # Create the raw client with auth setup
154
+ return AuthenticatedClient(**client_kwargs)
148
155
 
149
156
  def _create_httpx_client(self):
150
157
  """
@@ -437,4 +444,15 @@ class AlfrescoCoreClient:
437
444
  def __repr__(self) -> str:
438
445
  """String representation for debugging."""
439
446
  base_url = getattr(self._client_factory, 'base_url', 'unknown')
440
- return f"AlfrescoCoreClient(base_url='{base_url}')"
447
+ return f"AlfrescoCoreClient(base_url='{base_url}')"
448
+
449
+ # Export the main client class and all lazy-loaded sub-modules
450
+ # This ensures packaging systems include all dynamically accessed modules
451
+ __all__ = [
452
+ 'AlfrescoCoreClient',
453
+ # Lazy-loaded sub-clients (accessed via properties)
454
+ 'actions', 'activities', 'audit', 'comments', 'content', 'downloads',
455
+ 'favorites', 'groups', 'networks', 'nodes', 'people', 'preferences',
456
+ 'probes', 'queries', 'ratings', 'renditions', 'shared_links', 'sites',
457
+ 'tags', 'trashcan', 'versions'
458
+ ]
@@ -0,0 +1,11 @@
1
+ """
2
+ Downloads Operations Client - Level 3: Downloads-Specific Operations
3
+
4
+ This module provides downloads-specific operations within the Core API.
5
+ Part of the three-tier V1.1 architecture with complete 4-pattern detailed functions.
6
+ """
7
+
8
+ from .downloads_client import DownloadsClient
9
+ from . import models
10
+
11
+ __all__ = ['DownloadsClient', 'models']
@@ -0,0 +1,190 @@
1
+ """
2
+ Downloads Operations Client - Level 3: Downloads-Specific Operations
3
+
4
+ This module provides downloads-specific operations within the Core API.
5
+ Part of the three-tier V1.1 architecture with complete 4-pattern detailed functions.
6
+
7
+ Each operation provides 4 variants:
8
+ - operation(params) - basic sync with explicit parameters
9
+ - operation_async(params) - basic async with explicit parameters
10
+ - operation_detailed(params) - detailed sync with explicit parameters
11
+ - operation_detailed_async(params) - detailed async with explicit parameters
12
+
13
+ Perfect for MCP servers and documentation generation.
14
+ """
15
+
16
+ import asyncio
17
+ from typing import Optional, List, Union, Any
18
+ from httpx import Response
19
+
20
+ # Import from Level 3 (operation-specific models)
21
+ from .models import DownloadsResponse, DownloadsListResponse, CreateDownloadsRequest
22
+
23
+ # Import raw operations
24
+ try:
25
+ from ....raw_clients.alfresco_core_client.core_client.api.downloads import (
26
+ cancel_download as _cancel_download,
27
+ create_download as _create_download,
28
+ get_download as _get_download
29
+ )
30
+ RAW_OPERATIONS_AVAILABLE = True
31
+ except ImportError:
32
+ RAW_OPERATIONS_AVAILABLE = False
33
+
34
+
35
+ class DownloadsClient:
36
+ """
37
+ Downloads operations client with 4-pattern detailed functions.
38
+
39
+ Provides high-level methods for downloads management operations
40
+ that are essential for MCP servers and downloads workflows.
41
+
42
+ Each operation has 4 variants for maximum flexibility:
43
+ - Basic sync/async for simple use cases
44
+ - Detailed sync/async for full HTTP response access
45
+ """
46
+
47
+ def __init__(self, client_factory):
48
+ """Initialize with client factory for raw client access."""
49
+ self._client_factory = client_factory
50
+ self._raw_client = None
51
+
52
+ # Store raw operation references
53
+ if RAW_OPERATIONS_AVAILABLE:
54
+ self._cancel_download = _cancel_download
55
+ self._create_download = _create_download
56
+ self._get_download = _get_download
57
+
58
+ def _get_raw_client(self):
59
+ """Get or create the raw client."""
60
+ if self._raw_client is None:
61
+ # Import the raw core client directly
62
+ from ....raw_clients.alfresco_core_client.core_client.client import AuthenticatedClient
63
+
64
+ # Create the raw client with same auth setup
65
+ self._raw_client = AuthenticatedClient(
66
+ base_url=f"{self._client_factory.base_url}/alfresco/api/-default-/public/alfresco/versions/1",
67
+ token=self._client_factory.auth.get_auth_token(),
68
+ prefix=self._client_factory.auth.get_auth_prefix(),
69
+ verify_ssl=self._client_factory.verify_ssl
70
+ )
71
+ return self._raw_client
72
+
73
+ def get_httpx_client(self):
74
+ """
75
+ Get direct access to raw httpx client for advanced operations.
76
+
77
+ Perfect for MCP servers that need raw HTTP access.
78
+ """
79
+ return self._get_raw_client().get_httpx_client()
80
+
81
+ # ==================== CANCEL_DOWNLOAD OPERATION ====================
82
+
83
+ def cancel_download(self, download_id: str) -> Any:
84
+ """Cancel Download operation."""
85
+ from ....raw_clients.alfresco_core_client.core_client.api.downloads import cancel_download
86
+ return cancel_download.sync(client=self._get_raw_client(), download_id=download_id)
87
+
88
+ async def cancel_download_async(self, download_id: str) -> Any:
89
+ """Cancel Download operation (async)."""
90
+ from ....raw_clients.alfresco_core_client.core_client.api.downloads import cancel_download
91
+ return await cancel_download.asyncio(client=self._get_raw_client(), download_id=download_id)
92
+
93
+ def cancel_download_detailed(self, download_id: str) -> Response:
94
+ """Cancel Download operation (detailed)."""
95
+ from ....raw_clients.alfresco_core_client.core_client.api.downloads import cancel_download
96
+ return cancel_download.sync_detailed(client=self._get_raw_client(), download_id=download_id)
97
+
98
+ async def cancel_download_detailed_async(self, download_id: str) -> Response:
99
+ """Cancel Download operation (detailed, async)."""
100
+ from ....raw_clients.alfresco_core_client.core_client.api.downloads import cancel_download
101
+ return await cancel_download.asyncio_detailed(client=self._get_raw_client(), download_id=download_id)
102
+
103
+ # ==================== CREATE_DOWNLOAD OPERATION ====================
104
+
105
+ def create_download(self, body: Any, fields: Optional[List[str]] = None) -> Any:
106
+ """Create Download operation."""
107
+ from ....raw_clients.alfresco_core_client.core_client.api.downloads import create_download
108
+ from ....raw_clients.alfresco_core_client.core_client.types import UNSET
109
+ return create_download.sync(
110
+ client=self._get_raw_client(),
111
+ body=body,
112
+ fields=fields if fields is not None else UNSET
113
+ )
114
+
115
+ async def create_download_async(self, body: Any, fields: Optional[List[str]] = None) -> Any:
116
+ """Create Download operation (async)."""
117
+ from ....raw_clients.alfresco_core_client.core_client.api.downloads import create_download
118
+ from ....raw_clients.alfresco_core_client.core_client.types import UNSET
119
+ return await create_download.asyncio(
120
+ client=self._get_raw_client(),
121
+ body=body,
122
+ fields=fields if fields is not None else UNSET
123
+ )
124
+
125
+ def create_download_detailed(self, body: Any, fields: Optional[List[str]] = None) -> Response:
126
+ """Create Download operation (detailed)."""
127
+ from ....raw_clients.alfresco_core_client.core_client.api.downloads import create_download
128
+ from ....raw_clients.alfresco_core_client.core_client.types import UNSET
129
+ return create_download.sync_detailed(
130
+ client=self._get_raw_client(),
131
+ body=body,
132
+ fields=fields if fields is not None else UNSET
133
+ )
134
+
135
+ async def create_download_detailed_async(self, body: Any, fields: Optional[List[str]] = None) -> Response:
136
+ """Create Download operation (detailed, async)."""
137
+ from ....raw_clients.alfresco_core_client.core_client.api.downloads import create_download
138
+ from ....raw_clients.alfresco_core_client.core_client.types import UNSET
139
+ return await create_download.asyncio_detailed(
140
+ client=self._get_raw_client(),
141
+ body=body,
142
+ fields=fields if fields is not None else UNSET
143
+ )
144
+
145
+ # ==================== GET_DOWNLOAD OPERATION ====================
146
+
147
+ def get_download(self, download_id: str, fields: Optional[List[str]] = None) -> Any:
148
+ """Get Download operation."""
149
+ from ....raw_clients.alfresco_core_client.core_client.api.downloads import get_download
150
+ from ....raw_clients.alfresco_core_client.core_client.types import UNSET
151
+ return get_download.sync(
152
+ client=self._get_raw_client(),
153
+ download_id=download_id,
154
+ fields=fields if fields is not None else UNSET
155
+ )
156
+
157
+ async def get_download_async(self, download_id: str, fields: Optional[List[str]] = None) -> Any:
158
+ """Get Download operation (async)."""
159
+ from ....raw_clients.alfresco_core_client.core_client.api.downloads import get_download
160
+ from ....raw_clients.alfresco_core_client.core_client.types import UNSET
161
+ return await get_download.asyncio(
162
+ client=self._get_raw_client(),
163
+ download_id=download_id,
164
+ fields=fields if fields is not None else UNSET
165
+ )
166
+
167
+ def get_download_detailed(self, download_id: str, fields: Optional[List[str]] = None) -> Response:
168
+ """Get Download operation (detailed)."""
169
+ from ....raw_clients.alfresco_core_client.core_client.api.downloads import get_download
170
+ from ....raw_clients.alfresco_core_client.core_client.types import UNSET
171
+ return get_download.sync_detailed(
172
+ client=self._get_raw_client(),
173
+ download_id=download_id,
174
+ fields=fields if fields is not None else UNSET
175
+ )
176
+
177
+ async def get_download_detailed_async(self, download_id: str, fields: Optional[List[str]] = None) -> Response:
178
+ """Get Download operation (detailed, async)."""
179
+ from ....raw_clients.alfresco_core_client.core_client.api.downloads import get_download
180
+ from ....raw_clients.alfresco_core_client.core_client.types import UNSET
181
+ return await get_download.asyncio_detailed(
182
+ client=self._get_raw_client(),
183
+ download_id=download_id,
184
+ fields=fields if fields is not None else UNSET
185
+ )
186
+
187
+ def __repr__(self) -> str:
188
+ """String representation for debugging."""
189
+ base_url = getattr(self._client_factory, 'base_url', 'unknown')
190
+ return f"DownloadsClient(base_url='{base_url}')"