Skip to content

Commit

Permalink
Bring repo to functionality and usability standards.
Browse files Browse the repository at this point in the history
  • Loading branch information
toddbirchard committed Aug 7, 2024
1 parent 844ef43 commit 2603594
Show file tree
Hide file tree
Showing 10 changed files with 157 additions and 74 deletions.
4 changes: 4 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
GCP_BUCKET_URL="https://console.cloud.google.com/storage/browser/[BUCKET_NAME]"
GCP_BUCKET_NAME="[BUCKET_NAME]"
GCP_BUCKET_FOLDER_NAME="foo/bar"
GOOGLE_APPLICATION_CREDENTIALS="gcloud.json"
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ $(VIRTUAL_ENV):

.PHONY: run
run: env
$(LOCAL_PYTHON) -m main:init_script
$(LOCAL_PYTHON) -m main


.PHONY: install
Expand Down
23 changes: 15 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,25 @@ Source for the accompanying tutorial here: [https://hackersandslackers.com/googl

## Getting Started

Installation is recommended via Makefile
Get set up locally in two steps:

```shell
$ git clone https://github.com/hackersandslackers/googlecloud-storage-tutorial.git
$ cd googlecloud-storage-tutorial
$ make install
```
### Environment Variables

Replace the values in **.env.example** with your values and rename this file to **.env**:

* `GCP_BUCKET_URL`: URL of your Google Cloud Storage bucket.
* `GCP_BUCKET_NAME`: Name of your Google Cloud Storage bucket.
* `GCP_BUCKET_FOLDER_NAME`: Directory within your bucket to store and modify files.
* `GOOGLE_APPLICATION_CREDENTIALS`: Path to your Google Cloud Platform service account key file.

### Installation

### Usage
Get up and running with `make run`:

```shell
$ make run
git clone https://github.com/hackersandslackers/googlecloud-storage-tutorial.git
cd googlecloud-storage-tutorial
make run
```

-----
Expand Down
26 changes: 19 additions & 7 deletions config.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
"""Google Cloud Storage Configuration."""
from os import environ

# Google Cloud Storage
bucket_url = environ.get("GCP_BUCKET_URL")
bucket_name = environ.get("GCP_BUCKET_NAME")
bucket_dir = environ.get("GCP_BUCKET_FOLDER_NAME")
from os import environ, getenv, path

# Data
local_dir = environ.get("LOCAL_FOLDER")
from dotenv import load_dotenv

# Resolve local directory
BASE_DIR: str = path.abspath(path.dirname(__file__))

# Google Cloud Storage Secrets
environ["GOOGLE_APPLICATION_CREDENTIALS"] = "gcloud.json"
load_dotenv(path.join(BASE_DIR, ".env"))

BUCKET_URL = getenv("GCP_BUCKET_URL")
BUCKET_NAME = getenv("GCP_BUCKET_NAME")
BUCKET_DIR = getenv("GCP_BUCKET_FOLDER_NAME")

# Example local files
LOCAL_DIR = path.join(BASE_DIR, "files")
SAMPLE_CSV = path.join(BASE_DIR, "sample_csv.csv")
SAMPLE_IMG = path.join(BASE_DIR, "sample_image.jpg")
SAMPLE_TXT = path.join(BASE_DIR, "sample_text.txt")
Binary file removed files/peas.jpg
Binary file not shown.
15 changes: 0 additions & 15 deletions files/test.csv

This file was deleted.

19 changes: 13 additions & 6 deletions googlecloud_storage_tutorial/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
"""Initialize script demonstration"""
from config import bucket_dir, bucket_name, local_dir

from faker import Faker

from config import BUCKET_DIR, BUCKET_NAME, LOCAL_DIR
from googlecloud_storage_tutorial.storage import (
delete_file,
download_random_file,
Expand All @@ -8,10 +11,14 @@
upload_files,
)

fake = Faker()


def init_script():
print(upload_files(bucket_name))
print(list_files(bucket_name))
print(download_random_file(bucket_name, bucket_dir, local_dir))
print(rename_file(bucket_name, bucket_dir, "test.csv", "sample_test.csv"))
print(delete_file(bucket_name, bucket_dir, "sample_text.txt"))
"""Initialize script demonstration."""
print(upload_files(BUCKET_NAME, BUCKET_DIR, LOCAL_DIR))
print(list_files())
print(download_random_file(LOCAL_DIR))
print(rename_file(fake.unique.first_name()))
print(delete_file(BUCKET_NAME))
upload_files(BUCKET_NAME, BUCKET_DIR, LOCAL_DIR)
85 changes: 49 additions & 36 deletions googlecloud_storage_tutorial/storage.py
Original file line number Diff line number Diff line change
@@ -1,50 +1,49 @@
"""Programmatically interact with a Google Cloud Storage bucket."""

from os import listdir
from os.path import isfile, join
from random import randint
from typing import List, Optional
from typing import List, Optional, Tuple

from google.cloud import storage
from google.cloud.storage.blob import Blob

from config import bucket_dir, bucket_name, local_dir
from config import BUCKET_DIR, BUCKET_NAME

# Initialize Google Cloud Storage client
storage_client = storage.Client()
bucket = storage_client.get_bucket(bucket_name)
bucket = storage_client.get_bucket(BUCKET_NAME)


def upload_files(bucket_name: str, bucket_dir: str, local_dir: str) -> str:
def list_files() -> List[Optional[str]]:
"""
Upload files to GCP bucket.
List all objects with file extension in a GCP bucket.
:param str bucket_name: Human-readable GCP bucket name.
:param str bucket_dir: Bucket directory in which object exists.
:param str local_dir: Local file path to upload/download files.
:returns: str
:returns: List[Optional[str]]
"""
files = [f for f in listdir(local_dir) if isfile(join(local_dir, f))]
for file in files:
local_file = local_dir + file
blob = bucket.blob(bucket_dir + file)
blob.upload_from_filename(local_file)
return f"Uploaded {files.join(', ')} to '{bucket_name}' bucket."
blobs = bucket.list_blobs(prefix=BUCKET_DIR)
blob_file_list = [blob.name for blob in blobs if "." in blob.name]
return blob_file_list


def list_files(bucket_dir: str) -> List[Optional[str]]:
def pick_random_file() -> str:
"""
List all objects with file extension in a GCP bucket.
Pick a `random` file from GCP bucket.
:param str bucket_name: Human-readable GCP bucket name.
:param str bucket_dir: Bucket directory in which object exists.
:returns: List[Optional[str]]
:returns: str
"""
files = bucket.list_blobs(prefix=bucket_dir)
file_list = [file.name for file in files if "." in file.name]
return file_list
blobs = list_files()
rand = randint(0, len(blobs) - 1)
blob = bucket.blob(blobs[rand])
return blob, blob.name


def download_random_file(bucket_name: str, local_dir: str) -> str:
def download_random_file(local_dir: str) -> Tuple[Blob, str]:
"""
Download random file from GCP bucket.
Expand All @@ -54,15 +53,12 @@ def download_random_file(bucket_name: str, local_dir: str) -> str:
:returns: str
"""
fileList = list_files(bucket_name)
rand = randint(0, len(fileList) - 1)
blob = bucket.blob(fileList[rand])
file_name = blob.name.split("/")[-1]
blob.download_to_filename(local_dir + file_name)
return f"{file_name} downloaded from bucket."
blob, blob_filename = pick_random_file()
blob.download_to_filename(f"{local_dir}/{blob.name.split('/')[-1]}")
return blob, blob_filename


def delete_file(bucket_name: str, bucket_dir: str) -> str:
def delete_file(bucket_name: str) -> str:
"""
Delete file from GCP bucket.
Expand All @@ -71,13 +67,12 @@ def delete_file(bucket_name: str, bucket_dir: str) -> str:
:returns: str
"""
blob = bucket.blob(bucket_dir + file_name)
file_name = blob.name.split("/")[-1]
bucket.delete_blob(bucket_name + file_name)
return f"{file_name} deleted from bucket: {bucket_name}."
blob, blob_filename = pick_random_file()
bucket.delete_blob(blob_filename)
return f"{blob_filename} deleted from bucket: {bucket_name}."


def rename_file(bucket_dir: str, new_filename: str) -> str:
def rename_file(new_filename: str) -> str:
"""
Rename a file in GCP bucket.
Expand All @@ -87,7 +82,25 @@ def rename_file(bucket_dir: str, new_filename: str) -> str:
:returns: str
"""
blob = bucket.blob(bucket_dir + file_name)
file_name = blob.name.split("/")[-1]
blob, blob_filename = pick_random_file()
bucket.rename_blob(blob, new_name=new_filename)
return f"{file_name} renamed to {new_filename}."
return f"{blob_filename} renamed to {new_filename}."


def upload_files(bucket_name: str, bucket_dir: str, local_dir: str) -> str:
"""
Upload files to GCP bucket.
:param str bucket_name: Human-readable GCP bucket name.
:param str bucket_dir: Bucket directory in which object exists.
:param str local_dir: Local file path to upload/download files.
:returns: str
"""
files = [f for f in listdir(local_dir) if isfile(join(local_dir, f))]
for file in files:
local_file = f"{local_dir}/{file}"
print(f"local file = {local_file}\n")
blob = bucket.blob(f"{bucket_dir}/{file}")
blob.upload_from_filename(local_file)
return f"Uploaded {files} to '{bucket_name}' bucket."
55 changes: 54 additions & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ isort = "*"
flake8 = "*"
gunicorn = "*"
poetry-plugin-export = "^1.8.0"
faker = "^26.2.0"
python-dotenv = "^1.0.1"

[tool.poetry.scripts]
run = "main:init_script"
Expand Down

0 comments on commit 2603594

Please sign in to comment.