Skip to content

Commit

Permalink
Merge pull request #109 from roboflow/login
Browse files Browse the repository at this point in the history
Quickstart Backbones
  • Loading branch information
Jacobsolawetz authored Mar 14, 2023
2 parents 794f864 + 3861982 commit b22780d
Show file tree
Hide file tree
Showing 13 changed files with 730 additions and 52 deletions.
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ wget
tqdm>=4.41.0
PyYAML>=5.3.1
wget
requests_toolbelt
requests_toolbelt
113 changes: 110 additions & 3 deletions roboflow/__init__.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import json
import os
import sys
import time
from urllib.parse import urlparse

import requests

from roboflow.config import API_URL, APP_URL, DEMO_KEYS
from roboflow.config import API_URL, APP_URL, DEMO_KEYS, load_roboflow_api_key
from roboflow.core.project import Project
from roboflow.core.workspace import Workspace
from roboflow.util.general import write_line

__version__ = "0.2.34"
__version__ = "1.0.0"


def check_key(api_key, model, notebook, num_retries=0):
Expand Down Expand Up @@ -67,14 +70,118 @@ def auth(api_key):
return Roboflow(api_key, w)


def login(workspace=None, force=False):
conf_location = os.getenv(
"ROBOFLOW_CONFIG_DIR",
default=os.getenv("HOME") + "/.config/roboflow/config.json",
)

if os.path.isfile(conf_location) and not force:
write_line(
"You are already logged into Roboflow. To make a different login, run roboflow.login(force=True)."
)
return None
# we could eventually return the workspace object here
# return Roboflow().workspace()
elif os.path.isfile(conf_location) and force:
os.remove(conf_location)

if workspace is None:
write_line(
"visit " + APP_URL + "/auth-cli" " to get your authentication token."
)
else:
write_line(
"visit "
+ APP_URL
+ "/auth-cli/?workspace="
+ workspace
+ " to get your authentication token."
)

token = input("Paste the authentication here token here: ")

r_login = requests.get(APP_URL + "/query/cliAuthToken/" + token)

if r_login.status_code == 200:
r_login = r_login.json()

# make config directory if it doesn't exist
if not os.path.exists(os.path.dirname(conf_location)):
os.mkdir(os.path.dirname(conf_location))

r_login = {"workspaces": r_login}
# set first workspace as default workspace

default_workspace_id = list(r_login["workspaces"].keys())[0]
workspace = r_login["workspaces"][default_workspace_id]
r_login["RF_WORKSPACE"] = workspace["url"]

# write config file
with open(conf_location, "w") as f:
json.dump(r_login, f, indent=2)

else:
r_login.raise_for_status()

return None
# we could eventually return the workspace object here
# return Roboflow().workspace()


active_workspace = None


def initialize_roboflow():
global active_workspace

conf_location = os.getenv(
"ROBOFLOW_CONFIG_DIR",
default=os.getenv("HOME") + "/.config/roboflow/config.json",
)

if not os.path.isfile(conf_location):
raise RuntimeError(
"To use this method, you must first login - run roboflow.login()"
)
else:
if active_workspace == None:
active_workspace = Roboflow().workspace()

return active_workspace


def load_model(model_url):
operate_workspace = initialize_roboflow()

if "universe.roboflow.com" in model_url or "app.roboflow.com" in model_url:
parsed_url = urlparse(model_url)
path_parts = parsed_url.path.split("/")
project = path_parts[2]
version = int(path_parts[-1])
else:
raise (
"Model URL must be from either app.roboflow.com or universe.roboflow.com"
)

project = operate_workspace.project(project)
version = project.version(version)
model = version.model
return model


# continue distributing this object for back compatibility
class Roboflow:
def __init__(
self,
api_key="YOUR ROBOFLOW API KEY HERE",
api_key=None,
model_format="undefined",
notebook="undefined",
):
self.api_key = api_key
if self.api_key == None:
self.api_key = load_roboflow_api_key()

self.model_format = model_format
self.notebook = notebook
self.onboarding = False
Expand Down
78 changes: 70 additions & 8 deletions roboflow/config.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,66 @@
import json
import os


def get_conditional_configuration_variable(key, default):
"""Retrieves the configuration variable conditionally.
##1. check if variable is in environment
##2. check if variable is in config file
##3. return default value
Args:
key (string): The name of the configuration variable.
default (string): The default value of the configuration variable.
Returns:
string: The value of the conditional configuration variable.
"""

# default configuration location
conf_location = os.getenv(
"ROBOFLOW_CONFIG_DIR",
default=os.getenv("HOME") + "/.config/roboflow/config.json",
)

# read config file for roboflow if logged in from python or CLI
if os.path.exists(conf_location):
with open(conf_location) as f:
config = json.load(f)
else:
config = {}

if os.getenv(key) != None:
return os.getenv(key)
elif key in config.keys():
return config[key]
else:
return default


CLASSIFICATION_MODEL = os.getenv("CLASSIFICATION_MODEL", "ClassificationModel")
INSTANCE_SEGMENTATION_MODEL = "InstanceSegmentationModel"
OBJECT_DETECTION_MODEL = os.getenv("OBJECT_DETECTION_MODEL", "ObjectDetectionModel")
SEMANTIC_SEGMENTATION_MODEL = "SemanticSegmentationModel"
PREDICTION_OBJECT = os.getenv("PREDICTION_OBJECT", "Prediction")

API_URL = os.getenv("API_URL", "https://api.roboflow.com")
APP_URL = os.getenv("APP_URL", "https://app.roboflow.com")
UNIVERSE_URL = os.getenv("UNIVERSE_URL", "https://universe.roboflow.com")
INSTANCE_SEGMENTATION_URL = os.getenv(
API_URL = get_conditional_configuration_variable("API_URL", "https://api.roboflow.com")
APP_URL = get_conditional_configuration_variable("APP_URL", "https://app.roboflow.com")
UNIVERSE_URL = get_conditional_configuration_variable(
"UNIVERSE_URL", "https://universe.roboflow.com"
)

INSTANCE_SEGMENTATION_URL = get_conditional_configuration_variable(
"INSTANCE_SEGMENTATION_URL", "https://outline.roboflow.com"
)
SEMANTIC_SEGMENTATION_URL = os.getenv(
SEMANTIC_SEGMENTATION_URL = get_conditional_configuration_variable(
"SEMANTIC_SEGMENTATION_URL", "https://segment.roboflow.com"
)
OBJECT_DETECTION_URL = os.getenv(
OBJECT_DETECTION_URL = get_conditional_configuration_variable(
"SEMANTIC_SEGMENTATION_URL", "https://detect.roboflow.com"
)

CLIP_FEATURIZE_URL = os.getenv("CLIP_FEATURIZE_URL", "CLIP FEATURIZE URL NOT IN ENV")
OCR_URL = os.getenv("OCR_URL", "OCR URL NOT IN ENV")
CLIP_FEATURIZE_URL = get_conditional_configuration_variable(
"CLIP_FEATURIZE_URL", "CLIP FEATURIZE URL NOT IN ENV"
)
OCR_URL = get_conditional_configuration_variable("OCR_URL", "OCR URL NOT IN ENV")

DEMO_KEYS = ["coco-128-sample", "chess-sample-only-api-key"]

Expand All @@ -30,3 +70,25 @@
TYPE_SEMANTIC_SEGMENTATION = "semantic-segmentation"

DEFAULT_BATCH_NAME = "Pip Package Upload"

RF_WORKSPACES = get_conditional_configuration_variable("workspaces", default={})


def load_roboflow_api_key():
RF_WORKSPACE = get_conditional_configuration_variable("RF_WORKSPACE", default=None)
RF_WORKSPACES = get_conditional_configuration_variable("workspaces", default={})

# DEFAULT_WORKSPACE = get_conditional_configuration_variable("default_workspace", default=None)
if RF_WORKSPACE == None:
RF_API_KEY = None
else:
RF_API_KEY = None
for k in RF_WORKSPACES.keys():
workspace = RF_WORKSPACES[k]
if workspace["url"] == RF_WORKSPACE:
RF_API_KEY = workspace["apiKey"]
# ENV API_KEY OVERRIDE
if os.getenv("RF_API_KEY") != None:
RF_API_KEY = os.getenv("RF_API_KEY")

return RF_API_KEY
34 changes: 28 additions & 6 deletions roboflow/core/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ def versions(self):
workspace=self.__workspace,
project=self.__project_name,
public=self.public,
colors=self.colors,
)
version_array.append(version_object)
return version_array
Expand Down Expand Up @@ -192,12 +193,14 @@ def train(
},
speed=None,
checkpoint=None,
plot_in_notebook=False,
) -> bool:
"""
Ask the Roboflow API to train a previously exported version's dataset.
Args:
speed: Whether to train quickly or accurately. Note: accurate training is a paid feature. Default speed is `fast`.
checkpoint: A string representing the checkpoint to use while training
plot: Whether to plot the training loss curve. Default is False.
Returns:
True
RuntimeError: If the Roboflow API returns an error with a helpful JSON body
Expand All @@ -206,9 +209,11 @@ def train(

new_version = self.generate_version(settings=new_version_settings)
new_version = self.version(new_version)
new_version.train(speed=speed, checkpoint=checkpoint)
new_model = new_version.train(
speed=speed, checkpoint=checkpoint, plot_in_notebook=plot_in_notebook
)

return True
return new_model

def version(self, version_number, local=None):
"""Retrieves information about a specific version, and throws it into an object.
Expand Down Expand Up @@ -251,6 +256,7 @@ def version(self, version_number, local=None):
workspace=self.__workspace,
project=self.__project_name,
public=self.public,
colors=self.colors,
)
return vers

Expand Down Expand Up @@ -285,7 +291,7 @@ def __image_upload(
# Construct URL for local image upload
self.image_upload_url = "".join(
[
"https://api.roboflow.com/dataset/",
API_URL + "/dataset/",
project_name,
"/upload",
"?api_key=",
Expand Down Expand Up @@ -371,6 +377,9 @@ def __annotation_upload(self, annotation_path: str, image_id: str):
}

# Set annotation upload url

project_name = self.id.rsplit("/")[1]

self.annotation_upload_url = "".join(
[
API_URL + "/dataset/",
Expand Down Expand Up @@ -566,10 +575,23 @@ def single_upload(
annotation_response = self.__annotation_upload(annotation_path, image_id)
# Check if upload was a success
try:
annotation_success = annotation_response.json()["success"]
except Exception:
warnings.warn(f"Bad response: {response}")
response_data = annotation_response.json()
if "success" in response_data.keys():
annotation_success = True
elif "error" in response_data.keys():
warnings.warn(
f"Uploading annotation data for image failed: {str(response_data['error'])}"
)
annotation_success = False
else:
warnings.warn(
f"Uploading annotation data for image failed: {str(response_data)}"
)
annotation_success = False
except:
warnings.warn(f"Bad response: {response.status_code}")
annotation_success = False

# Give user warning that annotation failed to upload
if not annotation_success:
warnings.warn(
Expand Down
Loading

0 comments on commit b22780d

Please sign in to comment.