| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -61,6 +61,13 @@ Block/Unblock a user:: | |||
| 61 | 61 | user.block() | |
| 62 | 62 | user.unblock() | |
| 63 | 63 | ||
| 64 | + Set the avatar image for a user:: | ||
| 65 | + | ||
| 66 | + # the avatar image can be passed as data (content of the file) or as a file | ||
| 67 | + # object opened in binary mode | ||
| 68 | + user.avatar = open('path/to/file.png', 'rb') | ||
| 69 | + user.save() | ||
| 70 | + | ||
| 64 | 71 | User custom attributes | |
| 65 | 72 | ====================== | |
| 66 | 73 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -356,20 +356,25 @@ def copy_dict(dest, src): | |||
| 356 | 356 | ||
| 357 | 357 | opts = self._get_session_opts(content_type='application/json') | |
| 358 | 358 | ||
| 359 | - # don't set the content-type header when uploading files | ||
| 360 | - if files is not None: | ||
| 361 | - del opts["headers"]["Content-type"] | ||
| 362 | - | ||
| 363 | 359 | verify = opts.pop('verify') | |
| 364 | 360 | timeout = opts.pop('timeout') | |
| 365 | 361 | ||
| 362 | + # We need to deal with json vs. data when uploading files | ||
| 363 | + if files: | ||
| 364 | + data = post_data | ||
| 365 | + json = None | ||
| 366 | + del opts["headers"]["Content-type"] | ||
| 367 | + else: | ||
| 368 | + json = post_data | ||
| 369 | + data = None | ||
| 370 | + | ||
| 366 | 371 | # Requests assumes that `.` should not be encoded as %2E and will make | |
| 367 | 372 | # changes to urls using this encoding. Using a prepped request we can | |
| 368 | 373 | # get the desired behavior. | |
| 369 | 374 | # The Requests behavior is right but it seems that web servers don't | |
| 370 | 375 | # always agree with this decision (this is the case with a default | |
| 371 | 376 | # gitlab installation) | |
| 372 | - req = requests.Request(verb, url, json=post_data, params=params, | ||
| 377 | + req = requests.Request(verb, url, json=json, data=data, params=params, | ||
| 373 | 378 | files=files, **opts) | |
| 374 | 379 | prepped = self.session.prepare_request(req) | |
| 375 | 380 | prepped.url = sanitized_url(prepped.url) | |
@@ -506,7 +511,8 @@ def http_post(self, path, query_data={}, post_data={}, files=None, | |||
| 506 | 511 | error_message="Failed to parse the server message") | |
| 507 | 512 | return result | |
| 508 | 513 | ||
| 509 | - def http_put(self, path, query_data={}, post_data={}, **kwargs): | ||
| 514 | + def http_put(self, path, query_data={}, post_data={}, files=None, | ||
| 515 | + **kwargs): | ||
| 510 | 516 | """Make a PUT request to the Gitlab server. | |
| 511 | 517 | ||
| 512 | 518 | Args: | |
@@ -515,6 +521,7 @@ def http_put(self, path, query_data={}, post_data={}, **kwargs): | |||
| 515 | 521 | query_data (dict): Data to send as query parameters | |
| 516 | 522 | post_data (dict): Data to send in the body (will be converted to | |
| 517 | 523 | json) | |
| 524 | + files (dict): The files to send to the server | ||
| 518 | 525 | **kwargs: Extra data to make the query (e.g. sudo, per_page, page) | |
| 519 | 526 | ||
| 520 | 527 | Returns: | |
@@ -525,7 +532,7 @@ def http_put(self, path, query_data={}, post_data={}, **kwargs): | |||
| 525 | 532 | GitlabParsingError: If the json data could not be parsed | |
| 526 | 533 | """ | |
| 527 | 534 | result = self.http_request('put', path, query_data=query_data, | |
| 528 | - post_data=post_data, **kwargs) | ||
| 535 | + post_data=post_data, files=files, **kwargs) | ||
| 529 | 536 | try: | |
| 530 | 537 | return result.json() | |
| 531 | 538 | except Exception: | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -18,6 +18,7 @@ | |||
| 18 | 18 | import gitlab | |
| 19 | 19 | from gitlab import base | |
| 20 | 20 | from gitlab import cli | |
| 21 | + from gitlab import types as g_types | ||
| 21 | 22 | from gitlab import exceptions as exc | |
| 22 | 23 | ||
| 23 | 24 | ||
@@ -171,21 +172,29 @@ def create(self, data, **kwargs): | |||
| 171 | 172 | GitlabCreateError: If the server cannot perform the request | |
| 172 | 173 | """ | |
| 173 | 174 | self._check_missing_create_attrs(data) | |
| 175 | + files = {} | ||
| 174 | 176 | ||
| 175 | 177 | # We get the attributes that need some special transformation | |
| 176 | 178 | types = getattr(self, '_types', {}) | |
| 177 | - | ||
| 178 | 179 | if types: | |
| 179 | 180 | # Duplicate data to avoid messing with what the user sent us | |
| 180 | 181 | data = data.copy() | |
| 181 | 182 | for attr_name, type_cls in types.items(): | |
| 182 | 183 | if attr_name in data.keys(): | |
| 183 | 184 | type_obj = type_cls(data[attr_name]) | |
| 184 | - data[attr_name] = type_obj.get_for_api() | ||
| 185 | + | ||
| 186 | + # if the type if FileAttribute we need to pass the data as | ||
| 187 | + # file | ||
| 188 | + if issubclass(type_cls, g_types.FileAttribute): | ||
| 189 | + k = type_obj.get_file_name(attr_name) | ||
| 190 | + files[attr_name] = (k, data.pop(attr_name)) | ||
| 191 | + else: | ||
| 192 | + data[attr_name] = type_obj.get_for_api() | ||
| 185 | 193 | ||
| 186 | 194 | # Handle specific URL for creation | |
| 187 | 195 | path = kwargs.pop('path', self.path) | |
| 188 | - server_data = self.gitlab.http_post(path, post_data=data, **kwargs) | ||
| 196 | + server_data = self.gitlab.http_post(path, post_data=data, files=files, | ||
| 197 | + **kwargs) | ||
| 189 | 198 | return self._obj_cls(self, server_data) | |
| 190 | 199 | ||
| 191 | 200 | ||
@@ -232,15 +241,27 @@ def update(self, id=None, new_data={}, **kwargs): | |||
| 232 | 241 | path = '%s/%s' % (self.path, id) | |
| 233 | 242 | ||
| 234 | 243 | self._check_missing_update_attrs(new_data) | |
| 244 | + files = {} | ||
| 235 | 245 | ||
| 236 | 246 | # We get the attributes that need some special transformation | |
| 237 | 247 | types = getattr(self, '_types', {}) | |
| 238 | - for attr_name, type_cls in types.items(): | ||
| 239 | - if attr_name in new_data.keys(): | ||
| 240 | - type_obj = type_cls(new_data[attr_name]) | ||
| 241 | - new_data[attr_name] = type_obj.get_for_api() | ||
| 242 | - | ||
| 243 | - return self.gitlab.http_put(path, post_data=new_data, **kwargs) | ||
| 248 | + if types: | ||
| 249 | + # Duplicate data to avoid messing with what the user sent us | ||
| 250 | + new_data = new_data.copy() | ||
| 251 | + for attr_name, type_cls in types.items(): | ||
| 252 | + if attr_name in new_data.keys(): | ||
| 253 | + type_obj = type_cls(new_data[attr_name]) | ||
| 254 | + | ||
| 255 | + # if the type if FileAttribute we need to pass the data as | ||
| 256 | + # file | ||
| 257 | + if issubclass(type_cls, g_types.FileAttribute): | ||
| 258 | + k = type_obj.get_file_name(attr_name) | ||
| 259 | + files[attr_name] = (k, new_data.pop(attr_name)) | ||
| 260 | + else: | ||
| 261 | + new_data[attr_name] = type_obj.get_for_api() | ||
| 262 | + | ||
| 263 | + return self.gitlab.http_put(path, post_data=new_data, files=files, | ||
| 264 | + **kwargs) | ||
| 244 | 265 | ||
| 245 | 266 | ||
| 246 | 267 | class SetMixin(object): | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -44,3 +44,13 @@ def get_for_api(self): | |||
| 44 | 44 | class LowercaseStringAttribute(GitlabAttribute): | |
| 45 | 45 | def get_for_api(self): | |
| 46 | 46 | return str(self._value).lower() | |
| 47 | + | ||
| 48 | + | ||
| 49 | + class FileAttribute(GitlabAttribute): | ||
| 50 | + def get_file_name(self, attr_name=None): | ||
| 51 | + return attr_name | ||
| 52 | + | ||
| 53 | + | ||
| 54 | + class ImageAttribute(FileAttribute): | ||
| 55 | + def get_file_name(self, attr_name=None): | ||
| 56 | + return '%s.png' % attr_name if attr_name else 'image.png' | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -307,16 +307,19 @@ class UserManager(CRUDMixin, RESTManager): | |||
| 307 | 307 | ('email', 'username', 'name', 'password', 'reset_password', 'skype', | |
| 308 | 308 | 'linkedin', 'twitter', 'projects_limit', 'extern_uid', 'provider', | |
| 309 | 309 | 'bio', 'admin', 'can_create_group', 'website_url', | |
| 310 | - 'skip_confirmation', 'external', 'organization', 'location') | ||
| 310 | + 'skip_confirmation', 'external', 'organization', 'location', 'avatar') | ||
| 311 | 311 | ) | |
| 312 | 312 | _update_attrs = ( | |
| 313 | 313 | ('email', 'username', 'name'), | |
| 314 | 314 | ('password', 'skype', 'linkedin', 'twitter', 'projects_limit', | |
| 315 | 315 | 'extern_uid', 'provider', 'bio', 'admin', 'can_create_group', | |
| 316 | 316 | 'website_url', 'skip_confirmation', 'external', 'organization', | |
| 317 | - 'location') | ||
| 317 | + 'location', 'avatar') | ||
| 318 | 318 | ) | |
| 319 | - _types = {'confirm': types.LowercaseStringAttribute} | ||
| 319 | + _types = { | ||
| 320 | + 'confirm': types.LowercaseStringAttribute, | ||
| 321 | + 'avatar': types.ImageAttribute, | ||
| 322 | + } | ||
| 320 | 323 | ||
| 321 | 324 | ||
| 322 | 325 | class CurrentUserEmail(ObjectDeleteMixin, RESTObject): | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,6 +1,9 @@ | |||
| 1 | 1 | import base64 | |
| 2 | + import os | ||
| 2 | 3 | import time | |
| 3 | 4 | ||
| 5 | + import requests | ||
| 6 | + | ||
| 4 | 7 | import gitlab | |
| 5 | 8 | ||
| 6 | 9 | LOGIN = 'root' | |
@@ -49,6 +52,7 @@ | |||
| 49 | 52 | qG2ZdhHHmSK2LaQLFiSprUkikStNU9BqSQ== | |
| 50 | 53 | =5OGa | |
| 51 | 54 | -----END PGP PUBLIC KEY BLOCK-----''' | |
| 55 | + AVATAR_PATH = os.path.join(os.path.dirname(__file__), 'avatar.png') | ||
| 52 | 56 | ||
| 53 | 57 | ||
| 54 | 58 | # token authentication from config file | |
@@ -81,7 +85,11 @@ | |||
| 81 | 85 | ||
| 82 | 86 | # users | |
| 83 | 87 | new_user = gl.users.create({'email': 'foo@bar.com', 'username': 'foo', | |
| 84 | - 'name': 'foo', 'password': 'foo_password'}) | ||
| 88 | + 'name': 'foo', 'password': 'foo_password', | ||
| 89 | + 'avatar': open(AVATAR_PATH, 'rb')}) | ||
| 90 | + avatar_url = new_user.avatar_url.replace('gitlab.test', 'localhost:8080') | ||
| 91 | + uploaded_avatar = requests.get(avatar_url).content | ||
| 92 | + assert(uploaded_avatar == open(AVATAR_PATH, 'rb').read()) | ||
| 85 | 93 | users_list = gl.users.list() | |
| 86 | 94 | for user in users_list: | |
| 87 | 95 | if user.username == 'foo': | |
| Back | FazBrowse Home | New Git URL |
0 commit comments