Metadata-Version: 2.4
Name: groupdocs-search-net
Version: 0.0.0
Summary: GroupDocs.Search for Python via .NET - Full-text search and indexing for documents
Author-email: GroupDocs <support@groupdocs.com>
License-Expression: LicenseRef-Proprietary
Project-URL: Homepage, https://products.groupdocs.com/search/python-net/
Project-URL: Documentation, https://docs.groupdocs.com/search/python-net/
Keywords: search,full-text-search,index,query,document-search,groupdocs,dotnet
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: Unix
Classifier: Operating System :: MacOS
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Software Development :: Libraries
Classifier: Topic :: Utilities
Requires-Python: <3.15,>=3.5
Description-Content-Type: text/markdown

[![banner](https://raw.githubusercontent.com/groupdocs/groupdocs.github.io/master/img/banners/groupdocs-search-python-net-banner.png)](https://docs.groupdocs.com/search/python-net/)

[![PyPI](https://img.shields.io/pypi/v/groupdocs-search-net)](https://pypi.org/project/groupdocs-search-net/) [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/groupdocs-search-net)](https://pypi.org/project/groupdocs-search-net/)

[Product Page](https://products.groupdocs.com/search/python-net/) | [Docs](https://docs.groupdocs.com/search/python-net/) | [Demos](https://products.groupdocs.app/search/family) | [API Reference](https://reference.groupdocs.com/search/python-net/) | [Blog](https://blog.groupdocs.com/category/search/) | [Free Support](https://forum.groupdocs.com/c/search) | [Temporary License](https://purchase.groupdocs.com/temporary-license)

GroupDocs.Search for Python via .NET is a full-text search API. Build an index over a folder of documents, keep it on disk, and run keyword, phrase, wildcard, regular-expression, fuzzy, boolean, faceted, date-range, synonym and homophone queries against it, then highlight what was found. It reads Word, Excel, PowerPoint, PDF, email, eBook, web, archive and plain-text formats through one API, with no Microsoft Office or other software installed.

## Get Started

```bash
pip install groupdocs-search-net
```

Every release's wheels are also on [releases.groupdocs.com](https://releases.groupdocs.com/search/python-net/), for installing offline: download the one for your platform and run `pip install` on the file.

```python
from groupdocs.search import Index

index = Index("./index")            # creates the index folder, or opens an existing index
index.add("./documents")            # indexes every supported file in the folder
result = index.search("contract")
print("Found in %d documents (%d occurrences)" % (result.document_count, result.occurrence_count))
```

## How It Works

The package is a self-contained Python wheel (~250 MB) that bundles the embedded .NET runtime and everything needed to read, index and search documents: just `pip install` and start indexing. On Linux the system also needs ICU, and libgdiplus for presentations; on macOS, mono-libgdiplus for presentations (see *System Requirements* below). The wheel works across Python 3.5-3.14 on Windows, Linux, and macOS 13 or newer (Intel + Apple Silicon).

An index is a folder: build it once, reopen it in a later run, and `update()` re-indexes only the documents that changed. The first call into the engine takes about a second. On Windows, applying a license makes the first call take 15-30 seconds, once per process: the engine's license check takes that long there, in plain .NET too.

## Features

- **Indexing**: folders, single files, streams, in-memory text and extracted data; incremental `update()`, `optimize()`, merging indexes and deleting documents.
- **Query language**: keywords, phrases (`"..."`), wildcards (`?`, `*`), regular expressions (`^...`), boolean `AND` / `OR` / `NOT`, field (faceted) queries, date and numeric ranges, and queries built as objects.
- **Fuzzy, synonym, homophone and word-form search**, with editable dictionaries, spelling correction and stop words.
- **Highlighting**: whole documents or fragments, to HTML or plain text.
- **Events**: follow progress, skip or tag documents as they are indexed, and supply passwords, with `index.events.file_indexing += handler`.
- **Extensibility**: plain Python objects as custom text extractors for your own formats, word splitters, word-form providers, loggers and OCR connectors.
- **Reports**: indexing and search reports, the indexed documents and their stored text.
- **Cross-Platform**: Windows x64, Linux x64, macOS x64/ARM64.

## Common Tasks

- Build a searchable index over a document repository and query it from Python
- Find every document and occurrence containing a keyword or an exact phrase
- Match misspelled words with fuzzy search, or expand a query through synonyms
- Restrict a query to a field, such as the file name or the content
- Highlight the matches inside a found document for display
- Keep an index in sync as files are added, changed or removed
- Index a file format of your own with a custom extractor

## Supported File Formats

For the complete list, see [supported document formats](https://docs.groupdocs.com/search/python-net/supported-document-formats/).

| Category | Formats |
|---|---|
| **Word Processing** | DOC, DOCX, DOCM, DOT, DOTX, DOTM, RTF, TXT, ODT, OTT |
| **Spreadsheets** | XLS, XLSX, XLSM, XLSB, CSV, ODS, OTS |
| **Presentations** | PPT, PPTX, PPTM, PPS, PPSX, ODP |
| **Email** | EML, EMLX, MSG, PST, OST, MBOX |
| **Fixed-Layout** | PDF |
| **eBook** | EPUB, FB2, CHM |
| **Web & Markup** | HTM, HTML, MHT, MHTML, XML, MD |
| **Archives** | ZIP, and the documents inside them |

## Examples

### Create an index and add documents

```python
from groupdocs.search import Index

index = Index("./index")
index.add("./documents")
print("Indexed documents:", len(index.get_indexed_documents()))
```

### Simple, phrase, wildcard, regular-expression and boolean search

```python
from groupdocs.search import Index

index = Index("./index")
index.add("./documents")

for query in ["contract", '"service agreement"', "?ontract", "^cont.*", "contract AND NOT draft"]:
    result = index.search(query)
    print("%-28s %d documents" % (query, result.document_count))
```

### Fuzzy search

```python
from groupdocs.search import Index
from groupdocs.search.options import SearchOptions, SimilarityLevel

index = Index("./index")
index.add("./documents")

options = SearchOptions()
options.fuzzy_search.enabled = True
options.fuzzy_search.fuzzy_algorithm = SimilarityLevel(0.8)   # 0.0 (loose) .. 1.0 (strict)
result = index.search("contarct", options)                    # also matches "contract"
print(result.document_count, result.occurrence_count)
```

### Work with the results

```python
from groupdocs.search import Index

index = Index("./index")
index.add("./documents")

result = index.search("contract")
for found in result:
    print(found.document_info.file_path, "-", found.occurrence_count, "occurrences")
```

### Highlight the matches in a document

```python
from groupdocs.search import Index
from groupdocs.search.common import FileOutputAdapter
from groupdocs.search.highlighters import DocumentHighlighter
from groupdocs.search.options import OutputFormat

index = Index("./index")
index.add("./documents")

result = index.search("contract")
adapter = FileOutputAdapter(OutputFormat.HTML, "./highlighted.html")
index.highlight(result.get_found_document(0), DocumentHighlighter(adapter))
```

### Follow indexing with events

```python
from groupdocs.search import Index

index = Index("./index")

def on_file_indexing(sender, args):
    if args.document_full_path.endswith(".tmp"):
        args.skip_indexing = True            # leave this file out of the index

index.events.file_indexing += on_file_indexing
index.events.operation_progress_changed += lambda sender, args: print(
    "%d of %d documents" % (args.processed_documents, args.total_documents))
index.add("./documents")
```

A handler runs on the thread that raises the event. With `IndexingOptions.threads` above 1, or with `is_async`, that is an engine thread: an exception a handler raises there is printed to stderr and ignored. Unsubscribe with `-=`, or remove every handler with `index.events.file_indexing.clear()`.

### Index a format of your own

```python
from groupdocs.search import Index, IndexSettings

class LogExtractor(object):
    """Text of .log files, which the engine does not read on its own."""
    extensions = [".log"]

    def get_fields(self, source):             # a file path, or the engine's stream
        if isinstance(source, str):
            with open(source, encoding="utf-8") as f:
                text = f.read()
        else:
            text = source.read().decode("utf-8")
        return [("Content", text)]

settings = IndexSettings()
settings.custom_extractors.add(LogExtractor())
index = Index("./index", settings)
index.add("./logs")
print(index.search("timeout").document_count)
```

Loggers (`error(message)`, `trace(message)`), word splitters, word-form providers, document loaders and OCR connectors are plain Python objects or functions in the same way.

### Keep the index up to date

```python
from groupdocs.search import Index

index = Index("./index")
index.add("./documents")
# ... files in ./documents are added, changed or removed ...
index.update()        # re-indexes only what changed since the last add() or update()
index.optimize()      # merges index segments so searches stay fast
```

## AI Agent & LLM Friendly

This package is designed for seamless integration with AI agents, LLMs, and automated code generation tools.

- **`AGENTS.md` in the package** - AI coding assistants (Claude Code, Cursor, GitHub Copilot) auto-discover the API surface, usage patterns, and troubleshooting tips from the installed package. Setup per tool: [AI agents and LLM integration](https://docs.groupdocs.com/search/python-net/agents-and-llm-integration/)
- **MCP server** - connect your AI tool to GroupDocs documentation for on-demand API lookups:
  ```json
  { "mcpServers": { "groupdocs-docs": { "url": "https://docs.groupdocs.com/mcp" } } }
  ```
- **Machine-readable docs** - full documentation available as plain text for RAG and LLM context:
  - Single file: `https://docs.groupdocs.com/search/python-net/llms-full.txt`
  - Per page: append `.md` to any docs URL

## Evaluation Mode

The API works without a license in evaluation mode, with these limitations:
- An index takes at most 100 documents. `add()` does not raise for the rest: it leaves them out and reports "Number of indexed documents is restricted" through `index.events.error_occurred`.
- A search counts every match, but only the first 10 found documents can be read: `result.get_found_document(10)` raises `LicenseRestrictionException`.

To remove these limitations, apply a license or request a [temporary license](https://purchase.groupdocs.com/temporary-license):

```python
from groupdocs.search import License
License().set_license("path/to/license.lic")
```

Or set the environment variable, which is applied at the first call into the engine:
```bash
export GROUPDOCS_LIC_PATH="path/to/license.lic"
```

A license that cannot be applied raises `LicenseError` from that first call on, rather than falling back to evaluation mode.

## Troubleshooting

| Issue | Platform | Fix |
|---|---|---|
| The process aborts with `Couldn't find a valid ICU package`, or `DOTNET_SYSTEM_GLOBALIZATION_INVARIANT` errors | Linux | Install ICU (`apt-get install libicu-dev`) and do NOT set this variable |
| `is not a supported wheel on this platform` or `No matching distribution found for groupdocs-search-net` | Linux/macOS | The OS is older than the wheel needs (glibc 2.27, macOS 13), or pip is older than 20.3: `python -m pip install --upgrade pip`. On an Intel Mac, a Python built against an old SDK reports macOS 10.16 - use pip 24.1+ or `SYSTEM_VERSION_COMPAT=0 pip install groupdocs-search-net` |
| The first call takes 15-30 seconds when a license is applied | Windows | The engine's license check, once per process (measured in plain .NET too). Reuse the process for many operations |
| A presentation is not indexed, and `error_occurred` reports `The type initializer for 'Gdip' threw an exception` or a `NullReferenceException` | Linux/macOS | Install libgdiplus: `apt-get install libgdiplus` / `brew install mono-libgdiplus`. ODP and PPT files need it |
| `... cannot be changed because the index ... contains documents` | All | Since 26.10, dictionaries and the settings that split text into words can change only while the index is empty: set them before the first `add()` |
| `AttributeError: 'IndexSettings' object has no attribute ...` with a "Did you mean" hint | All | The property name is misspelled; assigning it would have had no effect on the engine |
| `AttributeError: 'file_indexing' is a .NET event` | All | Subscribe with `+=`, not `=`: `index.events.file_indexing += handler` |
| `LicenseRestrictionException: Only first 10 results can be returned`, or only 100 documents indexed | All | Evaluation mode: apply a license (above) |

## System Requirements

- Python 3.5 - 3.14, pip 20.3 or newer
- Windows x64, Linux x64, macOS x64/ARM64 - 64-bit Python only; there is no 32-bit Windows wheel
- Linux: glibc 2.27 or newer (e.g. Ubuntu 18.04+, Debian 10+, RHEL 8+), plus ICU and libgdiplus (`apt-get install libicu-dev libgdiplus`). No fonts are needed.
- macOS 13 or newer, Intel or Apple Silicon, plus `brew install mono-libgdiplus`
- libgdiplus serves presentations: without it, ODP and PPT files are left out of the index, and `error_occurred` says why. Every other format indexes without it.

## More Resources

- [Documentation](https://docs.groupdocs.com/search/python-net/)
- [Code Examples](https://github.com/groupdocs-search/GroupDocs.Search-for-Python-via-.NET)
- [Free Support Forum](https://forum.groupdocs.com/c/search)
- [Temporary License](https://purchase.groupdocs.com/temporary-license)

Also available for other platforms:
[.NET](https://products.groupdocs.com/search/net/) | [Java](https://products.groupdocs.com/search/java/) | [Node.js](https://products.groupdocs.com/search/nodejs-java/)

---

[Product Page](https://products.groupdocs.com/search/python-net/) | [Docs](https://docs.groupdocs.com/search/python-net/) | [Demos](https://products.groupdocs.app/search/family) | [API Reference](https://reference.groupdocs.com/search/python-net/) | [Blog](https://blog.groupdocs.com/category/search/) | [Free Support](https://forum.groupdocs.com/c/search) | [Temporary License](https://purchase.groupdocs.com/temporary-license)
