Metadata-Version: 2.4
Name: sharepoint_manager
Version: 0.1.2
Summary: Library for interacting with SharePoint using Microsoft Graph API
Author-email: Vinicius Benevides <viniciusm.benevides@gmail.com>
License-Expression: MIT
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: httpx<1,>=0.27
Requires-Dist: msal<2,>=1.37
Requires-Dist: requests<3,>=2.33
Provides-Extra: dev
Requires-Dist: build==1.5.0; extra == "dev"
Requires-Dist: cyclonedx-bom==7.1.0; extra == "dev"
Requires-Dist: pip-audit==2.10.1; extra == "dev"
Requires-Dist: pip-licenses==5.5.5; extra == "dev"
Requires-Dist: pyright==1.1.390; extra == "dev"
Requires-Dist: ruff==0.12.10; extra == "dev"
Requires-Dist: setuptools>=83.0.0; extra == "dev"
Requires-Dist: twine==6.1.0; extra == "dev"
Dynamic: license-file

# SharePoint Manager

<p align="center">
  <a href="LICENSE"><img alt="License" src="https://img.shields.io/github/license/VBenevides/sharepoint-manager"></a>
  <a href="https://github.com/VBenevides/sharepoint-manager/blob/main/VERSION"><img alt="Version" src="https://img.shields.io/badge/dynamic/regex.svg?url=https%3A%2F%2Fraw.githubusercontent.com%2FVBenevides%2Fsharepoint-manager%2Frefs%2Fheads%2Fmain%2FVERSION&search=%5E%28.%2B%29%24&label=version&color=blue"></a>
  <a href="https://github.com/VBenevides/sharepoint-manager/releases/latest"><img alt="Latest release" src="https://img.shields.io/github/v/release/VBenevides/sharepoint-manager?sort=semver"></a>
  <a href="https://github.com/VBenevides/sharepoint-manager/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/VBenevides/sharepoint-manager/actions/workflows/ci.yml/badge.svg"></a>
  <a href="https://github.com/VBenevides/sharepoint-manager/actions/workflows/codeql.yml"><img alt="CodeQL" src="https://github.com/VBenevides/sharepoint-manager/actions/workflows/codeql.yml/badge.svg"></a>
  <a href="https://github.com/VBenevides/sharepoint-manager/actions/workflows/security.yml"><img alt="Security" src="https://github.com/VBenevides/sharepoint-manager/actions/workflows/security.yml/badge.svg"></a>
</p>

Python clients for SharePoint through Microsoft Graph. Version 0.1.x is an
intentional breaking release from 0.0.x; see the [0.1.x contract](docs/contract-0.1.md).

## Support contract

- Python: 3.10–3.14
- Runtime dependencies: `httpx>=0.27,<1`, `msal>=1.37,<2`, and `requests>=2.33,<3`
- API: explicit operation targets, bounded by `OperationPolicy`, and typed with `SP*` exceptions
- Authentication: confidential app registration credentials or an explicitly
  configured service-account username/password flow
- Version: read from `VERSION`; 0.1.x does not preserve the 0.0.x API

The client does not grant end-user permissions. Configure Entra application
permissions outside this package. Prefer `Sites.Selected` and grant only the
required site and drive access; see [deployment permissions](docs/permissions.md).

## Install

```bash
python -m pip install sharepoint-manager
```

For development and release tooling:

```bash
python -m pip install -e ".[dev]"
```

Builds use PEP 517:

```bash
python -m build --sdist --wheel
```

## Quickstart

```python
import os

from sharepoint_manager import ClientCredential, SharepointManager

manager = SharepointManager(
    "https://tenant.sharepoint.com/sites/example",
    ClientCredential(
        os.environ["SP_CLIENT_ID"],
        os.environ["SP_CLIENT_SECRET"],
    ),
    document_folder_name="Documents",
)

try:
    files = manager.list_files("Reports/2026")
    manager.download_file("summary.csv", "./downloads", "Reports/2026")
finally:
    manager.close()
```

Use `with SharepointManager(...) as manager:` when the manager owns its HTTP
session. Never commit client secrets.

For a service account, configure the Entra app registration to allow public
client flows and pass `UserDelegatedCredential`:

```python
import os

from sharepoint_manager import SharepointManager, UserDelegatedCredential

manager = SharepointManager(
    "https://tenant.sharepoint.com/sites/example",
    UserDelegatedCredential(
        os.environ["SP_CLIENT_ID"],
        os.environ["SP_USERNAME"],
        os.environ["SP_PASSWORD"],
    ),
)
```

This username/password flow emits a warning because ROPC does not support MFA
or Conditional Access. Do not persist the service-account password. It is used
only for the initial MSAL token request; subsequent requests use the in-memory
MSAL cache and silent acquisition. If the cache misses, create a new manager
with the credentials. For managed identity, workload federation, certificates,
or another provider, inject a `TokenProvider` with `get_token(scope)`.

## Operations and guarantees

- Pass an explicit folder path, URL, or object to each operation. Managers have
  no mutable current-folder facade.
- Downloads use a sibling temporary file, verify QuickXorHash when Graph
  supplies one, and replace the destination only after successful completion.
- `upload_file` supports empty files and explicit `fail`, `replace`, or `rename`
  conflict behavior. An uncertain upload raises `SPAmbiguousWriteError` with
  recoverable session state.
- `iter_collection()` yields bounded `SPCollectionPage` values lazily.
  `iter_folder_delta()` yields `SPDeltaPage` values containing files, folders,
  tombstones, and checkpoint links. Persist `delta_link` in the caller's store.
- Approved SharePoint browser location URLs and sharing links support folder
  metadata, listing, creation, empty deletion, normalized permissions, and file
  transfers. Site/drive boundaries are checked before operations.

## Limits, retries, and errors

Pass `OperationPolicy` to set finite file, byte, page, item, depth, disk,
concurrency, retry, redirect, and wall-clock limits. Safe HTTP methods and
resumable upload chunks use the bounded transport retry policy; non-idempotent
Graph writes are not blindly replayed.

Catch stable public errors such as `SPAuthenticationError`,
`SPAuthorizationError`, `SPThrottledError`, `SPConflictError`,
`SPFolderNotFound`, `SPFileNotFound`, `SPDriveNotFound`, `SPValidationError`,
`SPDeadlineExceeded`, and
`SPAmbiguousWriteError`. Errors retain status, request ID, retryability, and
the original cause without embedding credentials, capability URLs, or names.

## Lifecycle and observability

Managers reuse one session and token provider and close owned resources through
`close()` or context-manager exit. Request concurrency is bounded by the
manager policy and each operation has an explicit target.
The `sharepoint_manager` logger defaults to `WARNING`, so routine INFO-level
`sharepoint event` records are quiet by default. Enable them explicitly when
needed:

```python
import logging

logging.getLogger("sharepoint_manager").setLevel(logging.INFO)
```

This logging threshold does not change the privacy-safe `telemetry` callback.
Normal logs contain no bearer tokens, credentials, capability URLs, filenames,
or permission members. Graph request IDs are retained as diagnostic fields.
Pass `telemetry=callback` to receive privacy-safe `graph.request`, `graph.page`,
`transfer`, and `auth.token_refresh` records with latency, status, retry,
bytes, page/item, throttle, failure-class, and partial-outcome fields.

## Development, migration, and support

See [CONTRIBUTING.md](CONTRIBUTING.md) for local checks and releases,
[SECURITY.md](SECURITY.md) for security reporting, and
[CHANGELOG.md](CHANGELOG.md) for version history. Use the explicit service-account
flow described in the [0.1.x contract](docs/contract-0.1.md), or inject a
delegated provider/service identity. Review the
[0.1.x migration note](docs/migration-0.1.md) before upgrading from 0.0.x.
