Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,13 @@ Content Understanding is ideal when you need capabilities beyond what built-in o
markitdown path-to-file.pdf --use-cu --cu-endpoint "<content_understanding_endpoint>"
```

The endpoint can also be set once in the environment, so callers only need `--use-cu`:

```bash
export MARKITDOWN_CU_ENDPOINT="<content_understanding_endpoint>"
markitdown path-to-file.pdf --use-cu
```

**Python API:**

```python
Expand Down Expand Up @@ -244,6 +251,13 @@ To use Microsoft Document Intelligence for conversion:
markitdown path-to-file.pdf -o document.md -d -e "<document_intelligence_endpoint>"
```

The endpoint can also be set once in the environment, so callers only need `-d`:

```bash
export MARKITDOWN_DOCINTEL_ENDPOINT="<document_intelligence_endpoint>"
markitdown path-to-file.pdf -o document.md -d
```

More information about how to set up an Azure Document Intelligence Resource can be found [here](https://learn.microsoft.com/en-us/azure/ai-services/document-intelligence/how-to-guides/create-document-intelligence-resource?view=doc-intel-4.0.0)

### Python API
Expand Down
9 changes: 7 additions & 2 deletions packages/markitdown/src/markitdown/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#
# SPDX-License-Identifier: MIT
import argparse
import os
import sys
import codecs
from typing import Any, Dict
Expand Down Expand Up @@ -98,13 +99,15 @@ def main():
"-e",
"--endpoint",
type=str,
help="Document Intelligence Endpoint. Required if using Document Intelligence.",
default=os.environ.get("MARKITDOWN_DOCINTEL_ENDPOINT") or None,
help="Document Intelligence Endpoint. Required if using Document Intelligence. Defaults to the MARKITDOWN_DOCINTEL_ENDPOINT environment variable.",
)

parser.add_argument(
"--cu-endpoint",
type=str,
help="Content Understanding Endpoint. Required if using --use-cu.",
default=os.environ.get("MARKITDOWN_CU_ENDPOINT") or None,
help="Content Understanding Endpoint. Required if using --use-cu. Defaults to the MARKITDOWN_CU_ENDPOINT environment variable.",
)

parser.add_argument(
Expand Down Expand Up @@ -204,6 +207,7 @@ def main():
if args.endpoint is None:
_exit_with_error(
"Document Intelligence Endpoint is required when using Document Intelligence."
"Pass -e/--endpoint or set MARKITDOWN_DOCINTEL_ENDPOINT."
Comment thread
afourney marked this conversation as resolved.
Outdated
)
elif args.filename is None:
_exit_with_error("Filename is required when using Document Intelligence.")
Expand All @@ -215,6 +219,7 @@ def main():
if args.cu_endpoint is None:
_exit_with_error(
"Content Understanding Endpoint (--cu-endpoint) is required when using --use-cu."
"Pass --cu-endpoint or set MARKITDOWN_CU_ENDPOINT."
)

cu_kwargs: Dict[str, Any] = {
Expand Down
72 changes: 72 additions & 0 deletions packages/markitdown/tests/test_cu_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"""

import io
import os
import sys
from unittest.mock import MagicMock, patch

Expand Down Expand Up @@ -801,6 +802,7 @@ def test_use_cu_without_endpoint_exits(self):
[sys.executable, "-m", "markitdown", "--use-cu", "fake.pdf"],
capture_output=True,
text=True,
env={**os.environ, "MARKITDOWN_CU_ENDPOINT": ""},
)
assert result.returncode != 0
assert (
Expand Down Expand Up @@ -961,3 +963,73 @@ def test_missing_deps_message(self):

assert "az-content-understanding" in str(exc_info.value)
assert exc_info.value.__cause__ is import_error


# ---------------------------------------------------------------------------
# Endpoint environment variables (issue #2326)
# ---------------------------------------------------------------------------


class TestEndpointEnvVars:
"""Endpoint flags fall back to operator-configured environment variables."""

@pytest.mark.parametrize(
"env_var, argv, kwarg",
[
(
"MARKITDOWN_CU_ENDPOINT",
["markitdown", "--use-cu", "fake.pdf"],
"cu_endpoint",
),
(
"MARKITDOWN_DOCINTEL_ENDPOINT",
["markitdown", "-d", "fake.pdf"],
"docintel_endpoint",
),
],
)
def test_endpoint_read_from_environment(self, monkeypatch, env_var, argv, kwarg):
"""With the env var set, the endpoint flag can be omitted entirely."""
from markitdown.__main__ import main

monkeypatch.setenv(env_var, "https://from-env")
monkeypatch.setattr(sys, "argv", argv)

with patch("markitdown.__main__.MarkItDown") as mock_markitdown:
main()

assert mock_markitdown.call_args.kwargs[kwarg] == "https://from-env"

def test_flag_overrides_environment(self, monkeypatch):
"""Fails if the env var is ever read after parsing instead of as an argparse default."""
from markitdown.__main__ import main

monkeypatch.setenv("MARKITDOWN_CU_ENDPOINT", "https://from-env")
monkeypatch.setattr(
sys,
"argv",
[
"markitdown",
"--use-cu",
"--cu-endpoint",
"https://from-flag",
"fake.pdf",
],
)

with patch("markitdown.__main__.MarkItDown") as mock_markitdown:
main()

assert mock_markitdown.call_args.kwargs["cu_endpoint"] == "https://from-flag"

def test_empty_environment_variable_is_treated_as_unset(self, monkeypatch, capsys):
"""An empty env var must not pass as a valid endpoint."""
from markitdown.__main__ import main

monkeypatch.setenv("MARKITDOWN_CU_ENDPOINT", "")
monkeypatch.setattr(sys, "argv", ["markitdown", "--use-cu", "fake.pdf"])

with pytest.raises(SystemExit):
main()

assert "MARKITDOWN_CU_ENDPOINT" in capsys.readouterr().out
Loading