Skip to content

Rlease v0.5.0 #51

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
4 changes: 2 additions & 2 deletions .github/workflows/black_linter.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
- uses: psf/black@stable
4 changes: 2 additions & 2 deletions .github/workflows/pytest-windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ jobs:
os: [windows-latest]

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pytest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
python-version: ["3.8", "3.12"]
python-version: ["3.9", "3.13"]
os: [ubuntu-20.04]

steps:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/python-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ jobs:
permissions:
id-token: write
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v2
uses: actions/setup-python@v5
with:
python-version: '3.x'
- name: Install dependencies
Expand Down
3 changes: 2 additions & 1 deletion MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
include requirements/*
include README.md
include pephubclient/pephub_oauth/*
include pephubclient/modules/*
include pephubclient/modules/*
include pephubclient/schemas/*
7 changes: 7 additions & 0 deletions Taskfile.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
version: '3'

tasks:
hello:
cmds:
- black .
silent: false
6 changes: 5 additions & 1 deletion docs/changelog.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
# Changelog

This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) and [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) format.


## [0.5.0] - 2025-03-31

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update correct date

### Added
- Added schemas CLI and Python methods for fetching schemas from PEPhub

## [0.4.5] - 2024-11-21
### Added
- Function for unwrapping PEPhub registry path
Expand Down
2 changes: 1 addition & 1 deletion pephubclient/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import coloredlogs

__app_name__ = "pephubclient"
__version__ = "0.4.5"
__version__ = "0.5.0"
__author__ = "Oleksandr Khoroshevskyi, Rafal Stepien"


Expand Down
4 changes: 4 additions & 0 deletions pephubclient/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from pephubclient import __app_name__, __version__
from pephubclient.helpers import call_client_func
from pephubclient.pephubclient import PEPHubClient
from pephubclient.schemas.schema_cli import schemas_app

_client = PEPHubClient()

Expand Down Expand Up @@ -88,3 +89,6 @@ def common(
),
):
pass


app.add_typer(schemas_app, name="schema")
8 changes: 8 additions & 0 deletions pephubclient/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,11 @@ class PEPExistsError(BasePephubclientException):
def __init__(self, message: Optional[str] = None):
self.message = message
super().__init__(self.message or self.default_message)


class FileDoesNotExistError(BasePephubclientException):
default_message = "File does not exist."

def __init__(self, message: Optional[str] = None):
self.message = message
super().__init__(self.message or self.default_message)
86 changes: 84 additions & 2 deletions pephubclient/helpers.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import json
from typing import Any, Callable, Optional, Union
from typing import Any, Callable, Optional, Union, Literal, Tuple
import peppy
import yaml
from pathlib import Path
import os
import pandas as pd
from peppy.const import (
Expand All @@ -21,7 +22,11 @@
from ubiquerg import parse_registry_path
from pydantic import ValidationError

from pephubclient.exceptions import PEPExistsError, ResponseError
from pephubclient.exceptions import (
PEPExistsError,
ResponseError,
BasePephubclientException,
)
from pephubclient.constants import RegistryPath
from pephubclient.files_manager import FilesManager
from pephubclient.models import ProjectDict
Expand Down Expand Up @@ -322,3 +327,80 @@ def save_pep(
parent_path=project_path, folder_name=file_name
)
_save_unzipped_pep(project, folder_path, force=force)


def open_schema(file_path: Union[str, Path]) -> dict:
"""
Open schema file that are saved in yaml or json format.

:param file_path: path to the schema file

:raises: FileNotFoundError - if file doesn't exist
:return: file object in dict format
"""
if isinstance(file_path, str):
file_path = Path(file_path)

if not file_path.is_file():
raise FileNotFoundError(
f"Provided schema file doesn't exist. File path: `{str(file_path)}`"
)

if file_path.suffix == ".yaml" or file_path.suffix == ".yml":
with open(file_path, "r") as file:
data = yaml.safe_load(file)

elif file_path.suffix == ".json":
with open(file_path, "r") as file:
data = json.load(file)
else:
raise BasePephubclientException(
f"Incorrect file format provided: '{file_path.suffix}'. "
"Only yaml and json formats are supported."
)

return data


def save_schema(
file_path: Union[str, Path],
schema_obj: dict,
format: Literal["json", "yaml"] = "yaml",
) -> None:
"""
Save dict object as file in json or yaml format

:param file_path: path to the file
:param schema_obj: content to be saved in the file
:param format: Format in which file should be saved on disc. Default: yaml

:return: File path.
"""

if format == "yaml":
schema_obj = yaml.dump(schema_obj)

elif format == "json":
schema_obj = json.dumps(schema_obj, indent=4)
else:
raise BasePephubclientException(f"Incorrect format provided: '{format}'")

with open(file_path, "w") as file:
file.write(schema_obj)


def schema_path_converter(schema_path: str) -> Tuple[str, str, str]:
"""
Convert schema path to namespace, name

:param schema_path: schema path that has structure: "namespace/name.yaml"
:return: tuple(namespace, name, version)
"""
if "/" in schema_path:
namespace, name_tag = schema_path.split("/")
if ":" in name_tag:
name, version = name_tag.split(":")
return namespace, name, version

return namespace, name_tag, "latest"
raise BasePephubclientException(f"Error in: '{schema_path}'")
6 changes: 6 additions & 0 deletions pephubclient/pephubclient.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
from pephubclient.pephub_oauth.pephub_oauth import PEPHubAuth
from pephubclient.modules.view import PEPHubView
from pephubclient.modules.sample import PEPHubSample
from pephubclient.schemas.schema import PEPHubSchema

urllib3.disable_warnings()

Expand All @@ -40,6 +41,7 @@ def __init__(self):

self.__view = PEPHubView(self.__jwt_data)
self.__sample = PEPHubSample(self.__jwt_data)
self.__schema = PEPHubSchema(self.__jwt_data)

@property
def view(self) -> PEPHubView:
Expand All @@ -49,6 +51,10 @@ def view(self) -> PEPHubView:
def sample(self) -> PEPHubSample:
return self.__sample

@property
def schema(self) -> PEPHubSchema:
return self.__schema

def login(self) -> NoReturn:
"""
Log in to PEPhub
Expand Down
Empty file.
17 changes: 17 additions & 0 deletions pephubclient/schemas/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from pephubclient.constants import PEPHUB_BASE_URL

PEPHUB_SCHEMA_BASE_URL = f"{PEPHUB_BASE_URL}api/v1/schemas/"

PEPHUB_SCHEMA_NEW_SCHEMA_URL = f"{PEPHUB_SCHEMA_BASE_URL}{{namespace}}/json"
PEPHUB_SCHEMA_NEW_VERSION_URL = (
f"{PEPHUB_SCHEMA_BASE_URL}{{namespace}}/{{schema_name}}/versions/json"
)
PEPHUB_SCHEMA_RECORD_URL = f"{PEPHUB_SCHEMA_BASE_URL}{{namespace}}/{{schema_name}}"
PEPHUB_SCHEMA_VERSIONS_URL = (
f"{PEPHUB_SCHEMA_BASE_URL}{{namespace}}/{{schema_name}}/versions"
)
PEPHUB_SCHEMA_VERSION_URL = (
f"{PEPHUB_SCHEMA_BASE_URL}{{namespace}}/{{schema_name}}/versions/{{version}}"
)

LATEST_VERSION = "latest"
77 changes: 77 additions & 0 deletions pephubclient/schemas/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
from pydantic import BaseModel, ConfigDict
from typing import Optional, Dict, Union, List
import datetime


class PaginationResult(BaseModel):
page: int = 0
page_size: int = 10
total: int


class SchemaVersionAnnotation(BaseModel):
"""
Schema version annotation model
"""

namespace: str
schema_name: str
version: str
contributors: Optional[str] = ""
release_notes: Optional[str] = ""
tags: Dict[str, Union[str, None]] = {}
release_date: datetime.datetime
last_update_date: datetime.datetime


class SchemaVersionResult(BaseModel):
pagination: PaginationResult
results: List[SchemaVersionAnnotation]


class NewSchemaVersionModel(BaseModel):
"""
Model for creating a new schema version from json
"""

contributors: Union[str, None] = None
release_notes: Union[str, None] = None
tags: Optional[Union[List[str], str, Dict[str, str], List[Dict[str, str]]]] = (
None,
)
version: str
schema_value: dict

model_config = ConfigDict(extra="forbid")


class NewSchemaRecordModel(NewSchemaVersionModel):
"""
Model for creating a new schema record from json
"""

schema_name: str
description: Union[str, None] = None
maintainers: Union[str, None] = None
lifecycle_stage: Union[str, None] = None
private: bool = False

model_config = ConfigDict(extra="forbid")


class UpdateSchemaRecordFields(BaseModel):
maintainers: Optional[Union[str, None]] = None
lifecycle_stage: Optional[Union[str, None]] = None
private: Optional[bool] = None
name: Optional[Union[str, None]] = None
description: Optional[Union[str, None]] = None

model_config = ConfigDict(extra="forbid")


class UpdateSchemaVersionFields(BaseModel):
contributors: Optional[Union[str, None]] = None
schema_value: Optional[Union[str, None]] = None
release_notes: Optional[Union[str, None]] = None

model_config = ConfigDict(extra="forbid")
Loading
Loading