Skip to content

Commit

Permalink
Merge pull request #368 from pcattori/tc-project
Browse files Browse the repository at this point in the history
tc.project and tc.mastering.project
  • Loading branch information
pcattori committed Apr 13, 2020
2 parents f88930c + 368aaa1 commit ad71caa
Show file tree
Hide file tree
Showing 11 changed files with 188 additions and 1 deletion.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
## 0.12.0-dev
**BETA**

Important: Do not use BETA features for production workflows.

- [#367](https://github.com/Datatamer/tamr-client/issues/367) Support for projects:
- generic projects via `tc.project`
- Mastering projects via `tc.mastering.project`

**BUG FIXES**
- `from_geo_features` now returns information on the operation.
Expand Down
4 changes: 3 additions & 1 deletion docs/beta.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,7 @@
* [Auth](beta/auth)
* [Dataset](beta/datasets)
* [Instance](beta/instance)
* [Mastering](beta/mastering)
* [Project](beta/project)
* [Response](beta/response)
* [Session](beta/session)
* [Session](beta/session)
3 changes: 3 additions & 0 deletions docs/beta/mastering.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Mastering

* [Project](/beta/mastering/project)
4 changes: 4 additions & 0 deletions docs/beta/mastering/project.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Mastering Project
=================

.. autoclass:: tamr_client.mastering.Project
10 changes: 10 additions & 0 deletions docs/beta/project.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Project
=======

.. autofunction:: tamr_client.project.from_resource_id

Exceptions
----------

.. autoclass:: tamr_client.project.NotFound
:no-inherited-members:
3 changes: 3 additions & 0 deletions tamr_client/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,6 @@
# dataframe
from tamr_client.datasets.dataframe import AmbiguousPrimaryKey
import tamr_client.datasets.dataframe as dataframe

import tamr_client.mastering as mastering
import tamr_client.project as project
8 changes: 8 additions & 0 deletions tamr_client/mastering/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# flake8: noqa
"""
Tamr - Mastering
See https://docs.tamr.com/docs/overall-workflow-mastering
"""

from tamr_client.mastering.project import Project
import tamr_client.mastering.project
34 changes: 34 additions & 0 deletions tamr_client/mastering/project.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from dataclasses import dataclass
from typing import Optional

import tamr_client as tc
from tamr_client.types import JsonDict


@dataclass(frozen=True)
class Project:
"""A Tamr Mastering project
See https://docs.tamr.com/reference/the-project-object
Args:
url
name
description
"""

url: tc.URL
name: str
description: Optional[str] = None


def _from_json(url: tc.URL, data: JsonDict) -> Project:
"""Make mastering project from JSON data (deserialize)
Args:
url: Project URL
data: Project JSON data from Tamr server
"""
return tc.mastering.Project(
url, name=data["name"], description=data.get("description")
)
65 changes: 65 additions & 0 deletions tamr_client/project.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
from typing import Union

import tamr_client as tc
from tamr_client.types import JsonDict

Project = Union[tc.mastering.Project]


class NotFound(Exception):
"""Raised when referencing (e.g. updating or deleting) a project
that does not exist on the server."""

pass


def from_resource_id(session: tc.Session, instance: tc.Instance, id: str) -> Project:
"""Get project by resource ID
Fetches project from Tamr server
Args:
instance: Tamr instance containing this dataset
id: Project ID
Raises:
NotFound: If no project could be found at the specified URL.
Corresponds to a 404 HTTP error.
requests.HTTPError: If any other HTTP error is encountered.
"""
url = tc.URL(instance=instance, path=f"projects/{id}")
return _from_url(session, url)


def _from_url(session: tc.Session, url: tc.URL) -> Project:
"""Get project by URL
Fetches project from Tamr server
Args:
url: Project URL
Raises:
NotFound: If no project could be found at the specified URL.
Corresponds to a 404 HTTP error.
requests.HTTPError: If any other HTTP error is encountered.
"""
r = session.get(str(url))
if r.status_code == 404:
raise NotFound(str(url))
data = tc.response.successful(r).json()
return _from_json(url, data)


def _from_json(url: tc.URL, data: JsonDict) -> Project:
"""Make project from JSON data (deserialize)
Args:
url: Project URL
data: Project JSON data from Tamr server
"""
proj_type = data["type"]
if proj_type == "DEDUP":
return tc.mastering.project._from_json(url, data)
else:
raise ValueError(f"Unrecognized project type '{proj_type}' in {repr(data)}")
19 changes: 19 additions & 0 deletions tests/tamr_client/data/mastering_project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"id": "unify://unified-data/v1/projects/1",
"name": "proj",
"description": "Mastering Project",
"type": "DEDUP",
"unifiedDatasetName": "proj_unified_dataset",
"created": {
"username": "admin",
"time": "2020-04-03T14:14:18.752Z",
"version": "18"
},
"lastModified": {
"username": "admin",
"time": "2020-04-03T14:14:20.115Z",
"version": "19"
},
"relativeId": "projects/1",
"externalId": "58bdbe72-3c08-427d-97bd-45b16d92c79c"
}
32 changes: 32 additions & 0 deletions tests/tamr_client/test_project.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import pytest
import responses

import tamr_client as tc
import tests.tamr_client.utils as utils


@responses.activate
def test_from_resource_id_mastering():
s = utils.session()
instance = utils.instance()

project_json = utils.load_json("mastering_project.json")
url = tc.URL(path="projects/1")
responses.add(responses.GET, str(url), json=project_json)

project = tc.project.from_resource_id(s, instance, "1")
assert isinstance(project, tc.mastering.Project)
assert project.name == "proj"
assert project.description == "Mastering Project"


@responses.activate
def test_from_resource_id_not_found():
s = utils.session()
instance = utils.instance()

url = tc.URL(path="projects/1")
responses.add(responses.GET, str(url), status=404)

with pytest.raises(tc.project.NotFound):
tc.project.from_resource_id(s, instance, "1")

0 comments on commit ad71caa

Please sign in to comment.