Skip to content

Commit

Permalink
Merge pull request #33 from Oxen-AI/feat/high-level-commands
Browse files Browse the repository at this point in the history
Feat/high level commands
  • Loading branch information
gschoeni committed Oct 15, 2023
2 parents a0b5c4a + b155489 commit cbe51ae
Show file tree
Hide file tree
Showing 16 changed files with 438 additions and 72 deletions.
14 changes: 7 additions & 7 deletions oxen/Cargo.lock

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

4 changes: 2 additions & 2 deletions oxen/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "oxen"
version = "0.2.0"
version = "0.3.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
Expand All @@ -15,7 +15,7 @@ log = "0.4.17"
pyo3-log = "0.8.1"
tokio = { version = "1", features = ["full"] }
pyo3-polars = "0.6.0"
liboxen = "0.9.1"
liboxen = "0.9.3"
# liboxen = { path = "../../rust/Oxen/src/lib" }

[build-dependencies]
Expand Down
6 changes: 5 additions & 1 deletion oxen/python/oxen/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
from oxen.op import Op
from oxen import auth
from oxen import loaders
from oxen.clone import clone
from oxen.init import init

# Names of public modules we want to expose
__all__ = [
Expand All @@ -23,9 +25,11 @@
"PyLocalRepo",
"PyStagedData",
"Op",
"clone",
"init",
"RemoteRepo",
"LocalRepo",
"auth",
"loaders",
"util",
"auth",
]
15 changes: 14 additions & 1 deletion oxen/python/oxen/auth.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,20 @@
from .oxen import auth, util
from typing import Optional

def config_auth(host: str, token: str, path: Optional[str] = None):

def config_auth(token: str, host: str = "hub.oxen.ai", path: Optional[str] = None):
"""
Configures authentication for a host.
Args:
token: `str`
The token to use for authentication.
host: `str`
The host to configure authentication for. Default: 'hub.oxen.ai'
path: `Optional[str]`
The path to save the authentication config to.
Defaults to $HOME/.config/oxen/user_config.toml
"""
if path is None:
path = f"{util.get_oxen_config_dir()}/user_config.toml"
if not path.endswith(".toml"):
Expand Down
50 changes: 50 additions & 0 deletions oxen/python/oxen/clone.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
from typing import Optional
from oxen.local_repo import LocalRepo


def clone(
repo_id: str,
path: Optional[str] = None,
host: str = "hub.oxen.ai",
branch: str = "main",
protocol: str = "https",
shallow=False,
all=False,
):
"""
Clone a repository
Args:
repo_id: `str`
Name of the repository in the format 'namespace/repo_name'.
For example 'ox/chatbot'
path: `Optional[str]`
The path to clone the repo to. Defaults to the name of the repository.
host: `str`
The host to connect to. Defaults to 'hub.oxen.ai'
branch: `str`
The branch name id to clone. Defaults to 'main'
protocol: `str`
The protocol to use. Defaults to 'https'
shallow: `bool`
Whether to do a shallow clone or not. Default: False
all: `bool`
Whether to clone the full commit history or not. Default: False
Returns:
[LocalRepo](/python-api/local_repo)
A LocalRepo object that can be used to interact with the cloned repo.
"""
# Verify repo_id format
if not "/" in repo_id:
raise ValueError(f"Invalid repo_id format: {repo_id}")
# Get repo name from repo_id
repo_name = repo_id.split("/")[1]
# Get path from repo_name if not provided
if path is None:
path = repo_name
# Get repo url
repo_url = f"{protocol}://{host}/{repo_id}"
# Clone repo
local_repo = LocalRepo(path)
local_repo.clone(repo_url, branch=branch, shallow=shallow, all=all)
return local_repo
19 changes: 19 additions & 0 deletions oxen/python/oxen/init.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from oxen.local_repo import LocalRepo


def init(
path: str,
):
"""
Initialize a [LocalRepo](/python-api/local_repo) at the given path.
Args:
path: `str`
The path to initialize the repo at.
Returns:
[LocalRepo](/python-api/local_repo)
A LocalRepo object that can be used to interact with the repo.
"""
# Init Repo
local_repo = LocalRepo(path)
return local_repo.init()
9 changes: 6 additions & 3 deletions oxen/python/oxen/local_repo.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from oxen import PyLocalRepo
import os


class LocalRepo:
"""
The LocalRepo class that allows you to interact with your local oxen repo.
Expand Down Expand Up @@ -43,8 +44,6 @@ def __init__(self, path: str = "", mkdir=False):
path = os.path.abspath(path)
if not os.path.exists(path) and mkdir:
os.makedirs(path)
elif not os.path.exists(path):
raise Exception(f"Path {path} does not exist.")

self._repo = PyLocalRepo(path)

Expand All @@ -57,6 +56,7 @@ def init(self):
Will create a .oxen folder to store all the versions and metadata.
"""
self._repo.init()
return self

def clone(self, url: str, branch: str = "main", shallow=False, all=False):
"""
Expand Down Expand Up @@ -148,6 +148,9 @@ def set_remote(self, name: str, url: str):
"""
self._repo.set_remote(name, url)

def create_remote(self, name: str):
self._repo.create_remote(name)

def push(self, remote_name: str = "origin", branch: str = "main"):
"""
Push data to a remote repo from a local repo.
Expand Down Expand Up @@ -186,4 +189,4 @@ def current_branch(self):
"""
Returns the current branch.
"""
return self._repo.current_branch()
return self._repo.current_branch()
49 changes: 47 additions & 2 deletions oxen/python/oxen/remote_repo.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,50 @@
import os

from typing import Optional
from oxen import PyRemoteRepo
from typing import List, Tuple
from .oxen import PyRemoteRepo, remote


def get_repo(name: str, host: str = "hub.oxen.ai"):
"""
Get a RemoteRepo object for the specified name. For example 'ox/CatDogBBox'.
Args:
name: `str`
Name of the repository in the format 'namespace/repo_name'.
host: `str`
The host to connect to. Defaults to 'hub.oxen.ai'
Returns:
[RemoteRepo](/python-api/remote_repo)
"""
return remote.get_repo(name, host)


def create_repo(
name: str,
description="",
is_public: bool = True,
host: str = "hub.oxen.ai",
files: List[Tuple[str, str]] = [],
):
"""
Create a new repository on the remote server.
Args:
name: `str`
Name of the repository in the format 'namespace/repo_name'.
description: `str`
Description of the repository. Only applicable to [OxenHub](https://oxen.ai).
is_public: `bool`
Whether the repository is public or private. Only applicable to [OxenHub](https://oxen.ai).
host: `str`
The host to connect to. Defaults to 'hub.oxen.ai'
files: `List[Tuple[str, str]]`
A list of tuples containing the path to the file and the contents of the file that you would like to seed the repository with.
Returns:
[RemoteRepo](/python-api/remote_repo)
"""
return remote.create_repo(name, description, is_public, host, files)


class RemoteRepo:
Expand Down Expand Up @@ -115,7 +158,9 @@ def ls(

return self._repo.ls(directory, page_num, page_size)

def download(self, remote_path: str, local_path: Optional[str] = None, revision: str = ""):
def download(
self, remote_path: str, local_path: Optional[str] = None, revision: str = ""
):
"""
Download a file or directory from the remote repo.
Expand Down
24 changes: 23 additions & 1 deletion oxen/python/oxen/user.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,38 @@
from .oxen import user, util
from typing import Optional


def config_user(name: str, email: str, path: Optional[str] = None):
"""
Configures user for a host.
Args:
name: `str`
The name to use for user.
email: `str`
The email to use for user.
path: `Optional[str]`
The path to save the user config to.
Defaults to $HOME/.config/oxen/user_config.toml
"""
if path is None:
path = f"{util.get_oxen_config_dir()}/user_config.toml"
if not path.endswith(".toml"):
raise ValueError(f"Path {path} must end with .toml")
return user.config_user(name, email, path)


def current_user(path: Optional[str] = None):
"""
Gets the current user.
Args:
path: `Optional[str]`
The path to load the user config from.
Defaults to $HOME/.config/oxen/user_config.toml
"""
if path is None:
path = f"{util.get_oxen_config_dir()}/user_config.toml"
if not path.endswith(".toml"):
raise ValueError(f"Path {path} must end with .toml")
return user.current_user(path)
return user.current_user(path)
31 changes: 7 additions & 24 deletions oxen/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
use std::path::PathBuf;

use error::PyOxenError;
use liboxen::{config::UserConfig, model::{repository::local_repository::FileNew, RepositoryNew}};
use py_remote_repo::PyRemoteRepo;
use pyo3::prelude::*;

pub mod error;
Expand All @@ -18,6 +14,7 @@ pub mod py_remote_repo;
pub mod py_paginated_dir_entries;
pub mod py_staged_data;
pub mod py_user;
pub mod remote;
pub mod user;
pub mod util;

Expand Down Expand Up @@ -70,25 +67,11 @@ fn oxen(py: Python, m: &PyModule) -> PyResult<()> {
user_module.add_function(wrap_pyfunction!(user::current_user, user_module)?)?;
m.add_submodule(user_module)?;

Ok(())
}
// Remote Module
let remote_module = PyModule::new(py, "remote")?;
remote_module.add_function(wrap_pyfunction!(remote::get_repo, remote_module)?)?;
remote_module.add_function(wrap_pyfunction!(remote::create_repo, remote_module)?)?;
m.add_submodule(remote_module)?;

// TODO: be able to pass in file list and contents from python
#[pyfunction]
pub fn create_remote_repo(namespace: String, name: String, host: String) -> Result<PyRemoteRepo, PyOxenError> {
let result = pyo3_asyncio::tokio::get_runtime().block_on(async {
let config = UserConfig::get()?;
let user = config.to_user();
let files: Vec<FileNew> = vec![FileNew {
path: PathBuf::from("README.md"),
contents: format!("# {}\n", &name),
}];
let repo = RepositoryNew::from_files(&namespace, &name, files, user);
liboxen::api::remote::repositories::create(repo, &host).await
})?;
Ok(PyRemoteRepo {
repo: result.clone(),
host: host.clone(),
revision: "main".to_string(),
})
Ok(())
}
Loading

0 comments on commit cbe51ae

Please sign in to comment.