diff --git a/docs/index.rst b/docs/index.rst index 32e8597..ccb9df6 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -28,6 +28,7 @@ Documentation organizations changelog credits + projects Contributing diff --git a/docs/projects.rst b/docs/projects.rst new file mode 100644 index 0000000..1cff24a --- /dev/null +++ b/docs/projects.rst @@ -0,0 +1,95 @@ +Projects +=========== + +Methods for searching and retrieving projects. + +ProjectClient +---------------- +.. class:: documentcloud.projects.ProjectClient + +The project client allows access to search, list, and retrieve projects. Accessed generally as ``client.projects``. + :: + +.. method:: list(self, **params) + + List all projects with optional filtering. Available filters include: + + - **contributors**: Filter by the unique identifier of a user associated with the project. + - **requests**: Filter by projects which have this request associated with it. + - **title**: Filter by the title of the project. Supports partial matches. Case sensitive. + + :param params: Query parameters to filter results, such as `contributors`, `requests`, and `title`. + :return: An :class:`APIResults` object containing the list of projects. + +.. method:: retrieve(self, project_id) + + Retrieve a specific project by its ID + + :param project_id: The unique ID of the project to retrieve. + :return: A :class:`Project` object representing the requested project. + +Project +---------------- +.. class:: documentcloud.projects.Project + + A representation of a single project. + + .. method:: str() + + Return a string representation of the project in format: `Project {id} - Title: {title}`. + + .. attribute:: id + + The unique numerical identifier for the project. + + .. attribute:: title + + The title of the project. + + .. attribute:: slug + + A short, URL-friendly version of the project's title. + + .. attribute:: summary + + A brief summary of the project. + + .. attribute:: description + + A detailed description of the project. + + .. attribute:: image + + The image associated with the project (if available). + + .. attribute:: private + + A boolean indicating whether the project is private (`true`) or public (`false`). + + .. attribute:: approved + + A boolean indicating whether the project has been approved (`true`) or not (`false`). + + .. attribute:: featured + + A boolean indicating whether the project is featured on the MuckRock site (`true`) or not (`false`). + + .. attribute:: contributors + + A list of user IDs representing the contributors to the project. + + .. attribute:: articles + + A list of article IDs associated with the project. + + .. attribute:: requests + + A list of request IDs associated with the project. + + .. attribute:: date_created + + The date and time when the project was created. If null, the creation date is not set. + + .. attribute:: date_approved + + The date and time when the project was approved. If null, the approval date is not set. \ No newline at end of file diff --git a/docs/users.rst b/docs/users.rst index bcd0c79..392ea15 100644 --- a/docs/users.rst +++ b/docs/users.rst @@ -7,7 +7,7 @@ UserClient ---------------- .. class:: documentcloud.users.UserClient - The user client allows access to search, list, and retrieve individual users. Accessed generally as ``client.organizations``. + The user client allows access to search, list, and retrieve individual users. Accessed generally as ``client.users``. :: >>> my_user = client.users.me() diff --git a/src/muckrock/client.py b/src/muckrock/client.py index 1362381..62f62a6 100644 --- a/src/muckrock/client.py +++ b/src/muckrock/client.py @@ -11,6 +11,7 @@ from .files import FileClient from .jurisdictions import JurisdictionClient from .organizations import OrganizationClient +from .projects import ProjectClient # Local Imports from .requests import RequestClient from .users import UserClient @@ -62,3 +63,4 @@ def __init__( self.files = FileClient(self) self.organizations = OrganizationClient(self) self.users = UserClient(self) + self.projects = ProjectClient(self) diff --git a/src/muckrock/projects.py b/src/muckrock/projects.py new file mode 100644 index 0000000..16c5053 --- /dev/null +++ b/src/muckrock/projects.py @@ -0,0 +1,47 @@ +""" +Projects +""" + +# Standard Library +import logging + +# Local +from .base import APIResults, BaseAPIClient, BaseAPIObject + +logger = logging.getLogger("projects") + + +class Project(BaseAPIObject): + """A single user object.""" + + api_path = "projects" + + def __str__(self): + return f"Project {self.id} - Title: {self.title}" # pylint:disable=no-member + + +class ProjectClient(BaseAPIClient): + """Client for interacting with users.""" + + api_path = "projects" + resource = Project + + def retrieve(self, project_id): + """ + Retrieve a single project by its ID. + + :param project_id: The ID of the project to retrieve. + :return: A project object. + """ + response = self.client.get(f"{self.api_path}/{project_id}/") + return Project(self.client, response.json()) + + def list(self, **params): + """ + List all projects with optional filtering. + + :param params: Query parameters to filter results + :return: APIResults containing User objects. + """ + response = self.client.get(self.api_path, params=params) + return APIResults(self.resource, self.client, response) diff --git a/src/muckrock/tests.py b/src/muckrock/tests.py index e30662b..6658149 100644 --- a/src/muckrock/tests.py +++ b/src/muckrock/tests.py @@ -171,3 +171,16 @@ def test_retrieve_users_nonstaff(regular_user_client): user_id = 1 with pytest.raises(DoesNotExistError): regular_user_client.users.retrieve(user_id) + + +def test_list_projects(muckrock_client): + projects = muckrock_client.projects.list() + assert projects, "Expected a non-empty list of communications." + print(projects) + + +def test_retrieve_projects(muckrock_client): + project_id = 10 + project = muckrock_client.projects.retrieve(project_id) + assert project.id == project_id, f"Expected request ID to be {project_id}." + print(project)