1 from collections
import namedtuple
4 from .facade
import ReturnMapping
, Type
, TypeEncoder
6 from .import _definitions
24 """A single websocket delta.
26 :ivar entity: The entity name, e.g. 'unit', 'application'
29 :ivar type: The delta type, e.g. 'add', 'change', 'remove'
32 :ivar data: The raw delta data
35 NOTE: The 'data' variable above is being incorrectly cross-linked by a
36 Sphinx bug: https://github.com/sphinx-doc/sphinx/issues/2549
39 _toSchema
= {'deltas': 'deltas'}
40 _toPy
= {'deltas': 'deltas'}
42 def __init__(self
, deltas
=None):
44 :param deltas: [str, str, object]
49 Change
= namedtuple('Change', 'entity type data')
50 change
= Change(*self
.deltas
)
52 self
.entity
= change
.entity
53 self
.type = change
.type
54 self
.data
= change
.data
57 def from_json(cls
, data
):
58 return cls(deltas
=data
)
61 class ResourcesFacade(Type
):
62 """Patch parts of ResourcesFacade to make it work.
65 @ReturnMapping(_client
.AddPendingResourcesResult
)
66 async def AddPendingResources(self
, application_tag
, charm_url
, resources
):
67 """Fix the calling signature of AddPendingResources.
69 The ResourcesFacade doesn't conform to the standard facade pattern in
70 the Juju source, which leads to the schemagened code not matching up
71 properly with the actual calling convention in the API. There is work
72 planned to fix this in Juju, but we have to work around it for now.
76 resources : typing.Sequence<+T_co>[~CharmResource]<~CharmResource>
77 Returns -> typing.Union[_ForwardRef('ErrorResult'),
78 typing.Sequence<+T_co>[str]]
80 # map input types to rpc msg
82 msg
= dict(type='Resources',
83 request
='AddPendingResources',
86 _params
['tag'] = application_tag
87 _params
['url'] = charm_url
88 _params
['resources'] = resources
89 reply
= await self
.rpc(msg
)
93 class AllWatcherFacade(Type
):
95 Patch rpc method of allwatcher to add in 'id' stuff.
98 async def rpc(self
, msg
):
99 if not hasattr(self
, 'Id'):
100 client
= _client
.ClientFacade
.from_connection(self
.connection
)
102 result
= await client
.WatchAll()
103 self
.Id
= result
.watcher_id
106 result
= await self
.connection
.rpc(msg
, encoder
=TypeEncoder
)
110 class Number(_definitions
.Number
):
112 This type represents a semver string.
114 Because it is not standard JSON, the typical from_json parsing fails and
115 the parsing must be handled specially.
117 See https://github.com/juju/version for more info.
119 numberPat
= re
.compile(r
'^(\d{1,9})\.(\d{1,9})(?:\.|-([a-z]+))(\d{1,9})(\.\d{1,9})?$') # noqa
121 def __init__(self
, major
=None, minor
=None, patch
=None, tag
=None,
122 build
=None, **unknown_fields
):
130 self
.major
= int(major
or '0')
131 self
.minor
= int(minor
or '0')
132 self
.patch
= int(patch
or '0')
134 self
.build
= int(build
or '0')
137 return '<Number major={} minor={} patch={} tag={} build={}>'.format(
138 self
.major
, self
.minor
, self
.patch
, self
.tag
, self
.build
)
141 return self
.serialize()
143 def __eq__(self
, other
):
145 isinstance(other
, type(self
)) and
146 other
.major
== self
.major
and
147 other
.minor
== self
.minor
and
148 other
.tag
== self
.tag
and
149 other
.patch
== self
.patch
and
150 other
.build
== self
.build
)
153 def from_json(cls
, data
):
155 if isinstance(data
, cls
):
159 elif isinstance(data
, dict):
161 elif isinstance(data
, str):
162 match
= cls
.numberPat
.match(data
)
165 'major': match
.group(1),
166 'minor': match
.group(2),
167 'tag': match
.group(3),
168 'patch': match
.group(4),
169 'build': (match
.group(5)[1:] if match
.group(5)
173 raise TypeError('Unable to parse Number version string: '
176 for k
, v
in parsed
.items():
177 d
[cls
._toPy
.get(k
, k
)] = v
184 s
= "{}.{}.{}".format(self
.major
, self
.minor
, self
.patch
)
186 s
= "{}.{}-{}{}".format(self
.major
, self
.minor
, self
.tag
,
189 s
= "{}.{}".format(s
, self
.build
)
193 return self
.serialize()
196 class Binary(_definitions
.Binary
):
198 This type represents a semver string with additional series and arch info.
200 Because it is not standard JSON, the typical from_json parsing fails and
201 the parsing must be handled specially.
203 See https://github.com/juju/version for more info.
205 binaryPat
= re
.compile(r
'^(\d{1,9})\.(\d{1,9})(?:\.|-([a-z]+))(\d{1,9})(\.\d{1,9})?-([^-]+)-([^-]+)$') # noqa
207 def __init__(self
, number
=None, series
=None, arch
=None, **unknown_fields
):
213 self
.number
= Number
.from_json(number
)
218 return '<Binary number={} series={} arch={}>'.format(
219 self
.number
, self
.series
, self
.arch
)
222 return self
.serialize()
224 def __eq__(self
, other
):
226 isinstance(other
, type(self
)) and
227 other
.number
== self
.number
and
228 other
.series
== self
.series
and
229 other
.arch
== self
.arch
)
232 def from_json(cls
, data
):
234 if isinstance(data
, cls
):
238 elif isinstance(data
, dict):
240 elif isinstance(data
, str):
241 match
= cls
.binaryPat
.match(data
)
245 'major': match
.group(1),
246 'minor': match
.group(2),
247 'tag': match
.group(3),
248 'patch': match
.group(4),
249 'build': (match
.group(5)[1:] if match
.group(5)
252 'series': match
.group(6),
253 'arch': match
.group(7),
256 raise TypeError('Unable to parse Binary version string: '
259 for k
, v
in parsed
.items():
260 d
[cls
._toPy
.get(k
, k
)] = v
265 return "{}-{}-{}".format(self
.number
.serialize(),
266 self
.series
, self
.arch
)
269 return self
.serialize()
272 class ConfigValue(_definitions
.ConfigValue
):
274 return '<{} source={} value={}>'.format(type(self
).__name
__,
279 class Resource(Type
):
280 _toSchema
= {'application': 'application',
281 'charmresource': 'CharmResource',
283 'pending_id': 'pending-id',
284 'timestamp': 'timestamp',
285 'username': 'username',
288 _toPy
= {'CharmResource': 'charmresource',
289 'application': 'application',
291 'pending-id': 'pending_id',
292 'timestamp': 'timestamp',
293 'username': 'username',
297 def __init__(self
, charmresource
=None, application
=None, id_
=None,
298 pending_id
=None, timestamp
=None, username
=None, name
=None,
299 origin
=None, **unknown_fields
):
301 charmresource : CharmResource
311 self
.charmresource
= _client
.CharmResource
.from_json(charmresource
)
313 self
.charmresource
= None
314 self
.application
= application
316 self
.pending_id
= pending_id
317 self
.timestamp
= timestamp
318 self
.username
= username