Skip to content

V2 SDK #10

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 21 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all 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
19 changes: 11 additions & 8 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,25 @@ jobs:
strategy:
matrix:
python-version:
- '2.7'
- '3.6'
- '3.7'
- '3.8'
- '3.9'
- '3.10'
- '3.11'
- '3.12'
- '3.13'
- '3.14.0-beta.4'
name: Python ${{ matrix.python-version }} sample
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v3
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install -r test-requirements.txt
- env:
- name: Run tests
env:
DETECTLANGUAGE_API_KEY: ${{ secrets.DETECTLANGUAGE_API_KEY }}
run: nosetests
run: pytest
53 changes: 53 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
name: Publish Python 🐍 distribution 📦 to PyPI

on:
release:
types: [published]

jobs:
build:
name: Build distribution 📦
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.x"
- name: Install pypa/build
run: >-
python3 -m
pip install
build
--user
- name: Build a binary wheel and a source tarball
run: python3 -m build
- name: Store the distribution packages
uses: actions/upload-artifact@v4
with:
name: python-package-distributions
path: dist/

publish-to-pypi:
name: >-
Publish Python 🐍 distribution 📦 to PyPI
needs:
- build
runs-on: ubuntu-latest
environment:
name: pypi
url: https://pypi.org/p/detectlanguage
permissions:
id-token: write # IMPORTANT: mandatory for trusted publishing

steps:
- name: Download all the dists
uses: actions/download-artifact@v4
with:
name: python-package-distributions
path: dist/
- name: Publish distribution 📦 to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
.env.local
.venv

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
Expand Down
25 changes: 25 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).


## v2.0.0

### Added
- `detect_batch` method for batch detections
- Proxy support

### Changed
- Switched to v3 API which uses updated language detection model
- ⚠️ `detect` method result fields are `language` and `score`

### Deprecated
- Calling `detect()` with list argument. Use `detect_batch` instead.
- `simple_detect()` - Use `detect_code()` instead. Will be removed in a future version.
- `user_status()` - Use `account_status()` instead. Will be removed in a future version.

### Removed
- Secure mode configuration. HTTPS is used by default.
48 changes: 21 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,68 +15,70 @@ You can get it by signing up at https://detectlanguage.com
pip install detectlanguage
```

### Upgrading

When upgrading please check [changelog](CHANGELOG.md) for breaking changes.

### Configuration

```python
import detectlanguage

detectlanguage.configuration.api_key = "YOUR API KEY"

# Enable secure mode (SSL) if you are passing sensitive data
# detectlanguage.configuration.secure = True
# You can use proxy if needed
# detectlanguage.configuration.proxies = {'https': 'https://user:pass@proxy:8080'}
```

## Usage

### Language detection
### Detect language

```python
detectlanguage.detect("Buenos dias señor")
detectlanguage.detect("Dolce far niente")
```

#### Result

```python
[{'isReliable': True, 'confidence': 12.04, 'language': 'es'}]
[{'language': 'it', 'score': 0.5074}]
```

### Simple language detection
### Detect single code

If you need just a language code you can use `simple_detect`. It returns just the language code.
If you need just a language code you can use `detect_code`.

```python
detectlanguage.simple_detect("Buenos dias señor")
detectlanguage.detect_code("Dolce far niente")
```

#### Result

```python
'es'
'it'
```

### Batch detection

It is possible to detect language of several texts with one request.
This method is faster than doing one request per text.
To use batch detection just pass array of texts to `detect` method.

```python
detectlanguage.detect(["Buenos dias señor", "Labas rytas"])
detectlanguage.detect_batch(["Dolce far niente", "Hello world"])
```

#### Result

Result is array of detections in the same order as the texts were passed.

```python
[ [ {'isReliable': True, 'confidence': 12.04, 'language': 'es'} ],
[ {'isReliable': True, 'confidence': 9.38, 'language': 'lt'} ] ]
[[{'language': 'it', 'score': 0.5074}], [{'language': 'en', 'score': 0.9098}]]
```

### Getting your account status
### Get your account status

```python
detectlanguage.user_status()
detectlanguage.account_status()
```

#### Result
Expand All @@ -87,25 +89,17 @@ detectlanguage.user_status()
'plan_expires': None }
```

### Getting list detectable languages
### Get list of supported languages

```python
detectlanguage.languages()
```

#### Result

Array of language codes and names.

## Contribution

You are welcome to patch and send GitHub pull requests.

### Testing

pip install -r requirements.txt
pip install -r test-requirements.txt
nosetests
```python
[{'code': 'aa', 'name': 'Afar'}, {'code': 'ab', 'name': 'Abkhazian'}, ...]
```

## License

Expand Down
7 changes: 5 additions & 2 deletions detectlanguage/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
__version__ = '1.5.0'
__version__ = '2.0.0'

from .exceptions import *
from .configuration import Configuration
from .client import Client
from .api import simple_detect, detect, user_status, languages
from .api import detect, detect_code, detect_batch, account_status, languages

# deprecated functions
from .api import simple_detect, user_status

configuration = Configuration()
client = Client(configuration)
59 changes: 54 additions & 5 deletions detectlanguage/api.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,64 @@
import detectlanguage
import warnings

def detect(data):
result = detectlanguage.client.post('detect', { 'q': data })
return result['data']['detections']
if isinstance(data, list):
_warn_deprecated('use detect_batch instead for multiple texts')
return detect_batch(data)

def simple_detect(data):
return detectlanguage.client.post('detect', { 'q': data })

def detect_code(data):
result = detect(data)
return result[0]['language']

def user_status():
return detectlanguage.client.get('user/status')
def detect_batch(data):
return detectlanguage.client.post('detect-batch', { 'q': data })

def account_status():
return detectlanguage.client.get('account/status')

def languages():
return detectlanguage.client.get('languages')


### DEPRECATED

def simple_detect(data):
"""
DEPRECATED: This function is deprecated and will be removed in a future version.
Use detect_code() instead.

Args:
data: Text to detect language for

Returns:
str: Language code of the detected language
"""
_warn_deprecated(
"simple_detect() is deprecated and will be removed in a future version. "
"Use detect_code() instead."
)
return detect_code(data)

def user_status():
"""
DEPRECATED: This function is deprecated and will be removed in a future version.
Use account_status() instead.

Returns:
dict: Account status information
"""
_warn_deprecated(
"user_status() is deprecated and will be removed in a future version. "
"Use account_status() instead."
)
return account_status()

def _warn_deprecated(message):
"""Internal utility function to emit deprecation warnings."""
warnings.warn(
message,
DeprecationWarning,
stacklevel=2
)
9 changes: 3 additions & 6 deletions detectlanguage/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ def __init__(self, configuration):
self.configuration = configuration

def get(self, path, payload = {}):
r = requests.get(self.url(path), params=payload, headers = self.headers(), timeout = self.configuration.timeout)
r = requests.get(self.url(path), params=payload, headers = self.headers(), timeout = self.configuration.timeout, proxies = self.configuration.proxies)
return self.handle_response(r)

def post(self, path, payload):
r = requests.post(self.url(path), json=payload, headers = self.headers(), timeout = self.configuration.timeout)
r = requests.post(self.url(path), json=payload, headers = self.headers(), timeout = self.configuration.timeout, proxies = self.configuration.proxies)
return self.handle_response(r)

def handle_response(self, r):
Expand All @@ -42,10 +42,7 @@ def handle_http_error(self, r, err):
raise DetectLanguageError(err)

def url(self, path):
return "%s://%s/%s/%s" % (self.protocol(), self.configuration.host, self.configuration.api_version, path)

def protocol(self):
return 'https' if self.configuration.secure else 'http'
return "https://%s/%s/%s" % (self.configuration.host, self.configuration.api_version, path)

def headers(self):
return {
Expand Down
4 changes: 2 additions & 2 deletions detectlanguage/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

class Configuration:
api_key = None
api_version = '0.2'
api_version = 'v3'
host = 'ws.detectlanguage.com'
user_agent = 'Detect Language API Python Client ' + detectlanguage.__version__
secure = False
timeout = 5
proxies = None # e.g., {'https': 'https://proxy.example.com:8080'}
13 changes: 13 additions & 0 deletions mise.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[tools]

[env]
_.file = ".env.local"
_.python.venv = { path = ".venv", create = true }

[tasks]
install-dev = "pip install -r requirements.txt && pip install -r test-requirements.txt && pip install build"
test = "pytest"
test-cov = "pytest --cov=detectlanguage --cov-report=term-missing"
test-verbose = "pytest -v"
console = "python -c \"import detectlanguage; import code; code.interact(local=locals())\""
build = "python3 -m build"
12 changes: 12 additions & 0 deletions pytest.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[tool:pytest]
testpaths = tests
python_files = test_*.py
python_classes = Test*
python_functions = test_*
addopts =
--verbose
--tb=short
--strict-markers
markers =
slow: marks tests as slow (deselect with '-m "not slow"')
integration: marks tests as integration tests
3 changes: 1 addition & 2 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
[metadata]
description-file = README.md

description_file = README.md
6 changes: 3 additions & 3 deletions test-requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
nose
nose-setenv
mock
pytest>=7.0.0
pytest-mock>=3.10.0
pytest-cov>=4.0.0
Loading