def add_row(self, **kwargs): values = {} count = 0 for f in [k for k in kwargs if kwargs[k] != ""]: field_name = anvil.regex.replace(f, "[^A-Za-z0-9\\-]", "").lower() values[field_name] = str(kwargs[f]) count += 1 if count == 0: print("[WARNING: Skipping adding empty row to worksheet]") return None try: added_row = rpc.call("anvil.private.google.sheets.add_row", self._obj["list_feed_url"], values, self.creds) except Exception: added_row = None # The returned row will only contain fields that already exist in the sheet. # If we didn't specify any existing fields, no row will be returned at all. existing_fields = self.fields missing_fields = [k for k in values if not k in existing_fields] if len(missing_fields) > 0: if not add_missing_fields: if added_row: added_row.delete() raise Exception("Field(s) not found: %s" % ",".join(missing_fields)) print("[WARNING: Adding missing fields to worksheet: %s]" % ",".join(missing_fields)) # Create the field headers for i in range(len(missing_fields)): h = self.get_cell(1, len(existing_fields) + i + 1) h.value = missing_fields[i] if added_row: # If we previously added the row, we need to set the newly-added fields for f in missing_fields: added_row[f] = values[f] else: # Otherwise, we never added the row in the first place, # so we just add it now directly. r = rpc.call("anvil.private.google.sheets.add_row", self._obj["list_feed_url"], values, self.creds) added_row = r return added_row
def request_page_fn(page_token): return rpc.call("anvil.private.google.drive.list_files", self.id, self.creds, page_token=page_token, trashed=False, mime_type='application/vnd.google-apps.folder')
def create_item_simple(title, folder, mime_type, creds): # Use simple metadata-only endpoint to create item. return wrap_item( rpc.call("anvil.private.google.drive.create_item_simple", title, folder.id, mime_type, creds), creds)
def next_page_fn(start_index): return rpc.call("anvil.private.google.sheets.list_rows", url, query, limit, self.creds, start_index=start_index)
def __init__(self, cap, query_dict): self._cap = cap self._fields, rows, self._next_start, self._done = rpc.call( "anvil.private.google.sheets.v4.list_initial_rows", cap, query_dict ) self._query_list = [query_dict.get(f) for f in self._fields] self._fields_old = {_old_field_transform(f): f for f in self._fields} self._iterator = iter(rows)
def create_item_multipart(title, folder, content, creds, content_type=None): return wrap_item( rpc.call("anvil.private.google.drive.create_item_multipart", title, folder.id, content, creds, content_type=content_type), creds)
def set_media(self, media): if not isinstance(media, anvil.Media): raise Exception("set_media() must be called with a Media object.") r = rpc.call("anvil.private.google.drive.set_content", self.id, media, self.creds) self._obj["mimeType"] = media.content_type return File(r, self.creds)
def get_by_id(self, id): if not isinstance(id, basestring): raise Exception("ID must be a string") if id == "": raise Exception("The empty string is not a valid ID") return wrap_item( rpc.call("anvil.private.google.drive.get_file_by_id", self.id, id, self.creds), self.creds)
def get_bytes(self, revision=None): if revision: url = revision["downloadUrl"] else: url = self._obj["downloadUrl"] b = rpc.call("anvil.private.google.drive.get_content", url, self.creds).get_bytes() self._obj["fileSize"] = len(b) return b
def __setattr__(self, name, value): if name == "value" or name == "input_value": val = rpc.call("anvil.private.google.sheets.v4.update_cell", self._other["capability"], value) self._obj["input_value"] = str(value) self._obj["value"] = val return val else: object.__setattr__(self, name, value)
def _query_single(parent_id, creds, **kwargs): r = rpc.call("anvil.private.google.drive.list_files", parent_id, creds, max_results=1, **kwargs) items = r["items"] if len(items) == 0: return None else: return items[0]
def __setattr__(self, name, value): if name == "value" or name == "inputValue": url = self._obj["edit_url"] r = rpc.call("anvil.private.google.sheets.update_cell", self._obj["id"], url, self.row, self.col, value, self.creds) self._obj = r return value else: object.__setattr__(self, name, value)
def __getattr__(self, python_name): id = None for df in anvil.google.get_config().get("app_files", []): if df["python_name"] == python_name: id = df["id"] break if id == None: raise Exception("No such app file: %s" % python_name) f = rpc.call("anvil.private.google.drive.get_app_file", id) return wrap_item(f, "google-delegated")
def add_row(self, **kwargs): fields = self.get_fields() fields_old = {_old_field_transform(field): field for field in fields} values = {fields_old.get(kw, kw): str(v) for kw, v in kwargs.items()} data = [values.get(field, "") for field in fields] added_row_index = rpc.call("anvil.private.google.sheets.v4.add_row", self._other["capability"], data) return Row({}, { "data": {field: value for field, value in zip(fields, data)}, "capability": self._other["capability"].narrow([int(added_row_index)]), "fields": fields, "fields_old": fields_old })
def set_bytes(self, content): # Use simple upload to replace content. Don't need to touch metadata. content_type = "text/plain" if not isinstance(content, str): raise Exception( "The 'bytes' of a file must be a Python string. To upload a Media object, use set_media()." ) r = rpc.call("anvil.private.google.drive.set_content", self.id, content, self.creds) self._obj["mimeType"] = content_type return File(r, self.creds)
def list_cells(self, min_row=None, max_row=None, min_col=None, max_col=None): if min_row is max_row is min_col is max_col is None: range_str = "" min_row = min_col = 1 else: min_col_str = index_to_col(min_col) max_col_str = index_to_col(max_col) range_str = min_col_str + str(min_row) + ":" + max_col_str + str(max_row) cells = rpc.call( "anvil.private.google.sheets.v4.list_cells", self._other["capability"], range_str, [min_row, min_col, max_row, max_col], ) return [ Cell(c, {"capability": self._other["capability"].narrow([c["row"], index_to_col(c["col"])])}) for c in cells ]
def request_page_fn(start_index): return rpc.call("anvil.private.google.sheets.list_worksheets", self._obj["worksheets_feed_url"], self.creds, start_index=start_index)
def get_cell(self, row, col): return Cell( rpc.call("anvil.private.google.sheets.get_cell", self._obj["cells_feed_url"], row, col, self.creds), self.creds)
def get_sheet(id, creds): s = Spreadsheet(**rpc.call("anvil.private.google.sheets.v4.get_sheet", id, creds)) return s
def update_metadata(item, metadata, creds): ctor = type(item) return ctor( rpc.call("anvil.private.google.drive.update_metadata", item.id, metadata, creds), creds)
def __setitem__(self, key, value): key = self._other["fields_old"].get(key, key) if key in self._other["data"]: rpc.call("anvil.private.google.sheets.v4.update_cell", self._other["capability"].narrow([index_to_col(self._other["fields"].index(key) + 1)]), value) else: raise KeyError(key)
def delete(self): rpc.call("anvil.private.google.sheets.v4.delete_row", self._other["capability"])
def get_user_files(): return Folder(rpc.call("anvil.private.google.drive.get_user_files"), "google-user")
def trash(self): ctor = type(self) return ctor( rpc.call("anvil.private.google.drive.trash", self.id, self.creds), self.creds)
def delete(self): rpc.call("anvil.private.google.drive.delete", self.id, self.creds)
def get_sheet(id, creds): return Sheet(rpc.call("anvil.private.google.sheets.get_sheet", id, creds), creds)
def request_page_fn(page_token): return rpc.call("anvil.private.google.drive.list_file_revisions", self.id, self.creds, page_token)
def _load_next_page(self): rows, self._next_start, self._done = rpc.call( "anvil.private.google.sheets.v4.list_more_rows", self._cap, self._query_list, self._next_start ) self._iterator = iter(rows)