Skip to content

Commit 2603594

Browse files
committed
Bring repo to functionality and usability standards.
1 parent 844ef43 commit 2603594

10 files changed

Lines changed: 157 additions & 74 deletions

File tree

.env.example

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
GCP_BUCKET_URL="https://console.cloud.google.com/storage/browser/[BUCKET_NAME]"
2+
GCP_BUCKET_NAME="[BUCKET_NAME]"
3+
GCP_BUCKET_FOLDER_NAME="foo/bar"
4+
GOOGLE_APPLICATION_CREDENTIALS="gcloud.json"

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ $(VIRTUAL_ENV):
3535

3636
.PHONY: run
3737
run: env
38-
$(LOCAL_PYTHON) -m main:init_script
38+
$(LOCAL_PYTHON) -m main
3939

4040

4141
.PHONY: install

README.md

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,25 @@ Source for the accompanying tutorial here: [https://hackersandslackers.com/googl
1313

1414
## Getting Started
1515

16-
Installation is recommended via Makefile
16+
Get set up locally in two steps:
1717

18-
```shell
19-
$ git clone https://github.com/hackersandslackers/googlecloud-storage-tutorial.git
20-
$ cd googlecloud-storage-tutorial
21-
$ make install
22-
```
18+
### Environment Variables
19+
20+
Replace the values in **.env.example** with your values and rename this file to **.env**:
21+
22+
* `GCP_BUCKET_URL`: URL of your Google Cloud Storage bucket.
23+
* `GCP_BUCKET_NAME`: Name of your Google Cloud Storage bucket.
24+
* `GCP_BUCKET_FOLDER_NAME`: Directory within your bucket to store and modify files.
25+
* `GOOGLE_APPLICATION_CREDENTIALS`: Path to your Google Cloud Platform service account key file.
26+
27+
### Installation
2328

24-
### Usage
29+
Get up and running with `make run`:
2530

2631
```shell
27-
$ make run
32+
git clone https://github.com/hackersandslackers/googlecloud-storage-tutorial.git
33+
cd googlecloud-storage-tutorial
34+
make run
2835
```
2936

3037
-----

config.py

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,22 @@
11
"""Google Cloud Storage Configuration."""
2-
from os import environ
32

4-
# Google Cloud Storage
5-
bucket_url = environ.get("GCP_BUCKET_URL")
6-
bucket_name = environ.get("GCP_BUCKET_NAME")
7-
bucket_dir = environ.get("GCP_BUCKET_FOLDER_NAME")
3+
from os import environ, getenv, path
84

9-
# Data
10-
local_dir = environ.get("LOCAL_FOLDER")
5+
from dotenv import load_dotenv
6+
7+
# Resolve local directory
8+
BASE_DIR: str = path.abspath(path.dirname(__file__))
9+
10+
# Google Cloud Storage Secrets
11+
environ["GOOGLE_APPLICATION_CREDENTIALS"] = "gcloud.json"
12+
load_dotenv(path.join(BASE_DIR, ".env"))
13+
14+
BUCKET_URL = getenv("GCP_BUCKET_URL")
15+
BUCKET_NAME = getenv("GCP_BUCKET_NAME")
16+
BUCKET_DIR = getenv("GCP_BUCKET_FOLDER_NAME")
17+
18+
# Example local files
19+
LOCAL_DIR = path.join(BASE_DIR, "files")
20+
SAMPLE_CSV = path.join(BASE_DIR, "sample_csv.csv")
21+
SAMPLE_IMG = path.join(BASE_DIR, "sample_image.jpg")
22+
SAMPLE_TXT = path.join(BASE_DIR, "sample_text.txt")

files/peas.jpg

-32.1 KB
Binary file not shown.

files/test.csv

Lines changed: 0 additions & 15 deletions
This file was deleted.
Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
"""Initialize script demonstration"""
2-
from config import bucket_dir, bucket_name, local_dir
2+
3+
from faker import Faker
4+
5+
from config import BUCKET_DIR, BUCKET_NAME, LOCAL_DIR
36
from googlecloud_storage_tutorial.storage import (
47
delete_file,
58
download_random_file,
@@ -8,10 +11,14 @@
811
upload_files,
912
)
1013

14+
fake = Faker()
15+
1116

1217
def init_script():
13-
print(upload_files(bucket_name))
14-
print(list_files(bucket_name))
15-
print(download_random_file(bucket_name, bucket_dir, local_dir))
16-
print(rename_file(bucket_name, bucket_dir, "test.csv", "sample_test.csv"))
17-
print(delete_file(bucket_name, bucket_dir, "sample_text.txt"))
18+
"""Initialize script demonstration."""
19+
print(upload_files(BUCKET_NAME, BUCKET_DIR, LOCAL_DIR))
20+
print(list_files())
21+
print(download_random_file(LOCAL_DIR))
22+
print(rename_file(fake.unique.first_name()))
23+
print(delete_file(BUCKET_NAME))
24+
upload_files(BUCKET_NAME, BUCKET_DIR, LOCAL_DIR)
Lines changed: 49 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,49 @@
11
"""Programmatically interact with a Google Cloud Storage bucket."""
2+
23
from os import listdir
34
from os.path import isfile, join
45
from random import randint
5-
from typing import List, Optional
6+
from typing import List, Optional, Tuple
67

78
from google.cloud import storage
9+
from google.cloud.storage.blob import Blob
810

9-
from config import bucket_dir, bucket_name, local_dir
11+
from config import BUCKET_DIR, BUCKET_NAME
1012

13+
# Initialize Google Cloud Storage client
1114
storage_client = storage.Client()
12-
bucket = storage_client.get_bucket(bucket_name)
15+
bucket = storage_client.get_bucket(BUCKET_NAME)
1316

1417

15-
def upload_files(bucket_name: str, bucket_dir: str, local_dir: str) -> str:
18+
def list_files() -> List[Optional[str]]:
1619
"""
17-
Upload files to GCP bucket.
20+
List all objects with file extension in a GCP bucket.
1821
1922
:param str bucket_name: Human-readable GCP bucket name.
2023
:param str bucket_dir: Bucket directory in which object exists.
21-
:param str local_dir: Local file path to upload/download files.
2224
23-
:returns: str
25+
:returns: List[Optional[str]]
2426
"""
25-
files = [f for f in listdir(local_dir) if isfile(join(local_dir, f))]
26-
for file in files:
27-
local_file = local_dir + file
28-
blob = bucket.blob(bucket_dir + file)
29-
blob.upload_from_filename(local_file)
30-
return f"Uploaded {files.join(', ')} to '{bucket_name}' bucket."
27+
blobs = bucket.list_blobs(prefix=BUCKET_DIR)
28+
blob_file_list = [blob.name for blob in blobs if "." in blob.name]
29+
return blob_file_list
3130

3231

33-
def list_files(bucket_dir: str) -> List[Optional[str]]:
32+
def pick_random_file() -> str:
3433
"""
35-
List all objects with file extension in a GCP bucket.
34+
Pick a `random` file from GCP bucket.
3635
3736
:param str bucket_name: Human-readable GCP bucket name.
38-
:param str bucket_dir: Bucket directory in which object exists.
3937
40-
:returns: List[Optional[str]]
38+
:returns: str
4139
"""
42-
files = bucket.list_blobs(prefix=bucket_dir)
43-
file_list = [file.name for file in files if "." in file.name]
44-
return file_list
40+
blobs = list_files()
41+
rand = randint(0, len(blobs) - 1)
42+
blob = bucket.blob(blobs[rand])
43+
return blob, blob.name
4544

4645

47-
def download_random_file(bucket_name: str, local_dir: str) -> str:
46+
def download_random_file(local_dir: str) -> Tuple[Blob, str]:
4847
"""
4948
Download random file from GCP bucket.
5049
@@ -54,15 +53,12 @@ def download_random_file(bucket_name: str, local_dir: str) -> str:
5453
5554
:returns: str
5655
"""
57-
fileList = list_files(bucket_name)
58-
rand = randint(0, len(fileList) - 1)
59-
blob = bucket.blob(fileList[rand])
60-
file_name = blob.name.split("/")[-1]
61-
blob.download_to_filename(local_dir + file_name)
62-
return f"{file_name} downloaded from bucket."
56+
blob, blob_filename = pick_random_file()
57+
blob.download_to_filename(f"{local_dir}/{blob.name.split('/')[-1]}")
58+
return blob, blob_filename
6359

6460

65-
def delete_file(bucket_name: str, bucket_dir: str) -> str:
61+
def delete_file(bucket_name: str) -> str:
6662
"""
6763
Delete file from GCP bucket.
6864
@@ -71,13 +67,12 @@ def delete_file(bucket_name: str, bucket_dir: str) -> str:
7167
7268
:returns: str
7369
"""
74-
blob = bucket.blob(bucket_dir + file_name)
75-
file_name = blob.name.split("/")[-1]
76-
bucket.delete_blob(bucket_name + file_name)
77-
return f"{file_name} deleted from bucket: {bucket_name}."
70+
blob, blob_filename = pick_random_file()
71+
bucket.delete_blob(blob_filename)
72+
return f"{blob_filename} deleted from bucket: {bucket_name}."
7873

7974

80-
def rename_file(bucket_dir: str, new_filename: str) -> str:
75+
def rename_file(new_filename: str) -> str:
8176
"""
8277
Rename a file in GCP bucket.
8378
@@ -87,7 +82,25 @@ def rename_file(bucket_dir: str, new_filename: str) -> str:
8782
8883
:returns: str
8984
"""
90-
blob = bucket.blob(bucket_dir + file_name)
91-
file_name = blob.name.split("/")[-1]
85+
blob, blob_filename = pick_random_file()
9286
bucket.rename_blob(blob, new_name=new_filename)
93-
return f"{file_name} renamed to {new_filename}."
87+
return f"{blob_filename} renamed to {new_filename}."
88+
89+
90+
def upload_files(bucket_name: str, bucket_dir: str, local_dir: str) -> str:
91+
"""
92+
Upload files to GCP bucket.
93+
94+
:param str bucket_name: Human-readable GCP bucket name.
95+
:param str bucket_dir: Bucket directory in which object exists.
96+
:param str local_dir: Local file path to upload/download files.
97+
98+
:returns: str
99+
"""
100+
files = [f for f in listdir(local_dir) if isfile(join(local_dir, f))]
101+
for file in files:
102+
local_file = f"{local_dir}/{file}"
103+
print(f"local file = {local_file}\n")
104+
blob = bucket.blob(f"{bucket_dir}/{file}")
105+
blob.upload_from_filename(local_file)
106+
return f"Uploaded {files} to '{bucket_name}' bucket."

poetry.lock

Lines changed: 54 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ isort = "*"
2020
flake8 = "*"
2121
gunicorn = "*"
2222
poetry-plugin-export = "^1.8.0"
23+
faker = "^26.2.0"
24+
python-dotenv = "^1.0.1"
2325

2426
[tool.poetry.scripts]
2527
run = "main:init_script"

0 commit comments

Comments
 (0)