pybc365 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pybc365-0.1.0/LICENSE +21 -0
- pybc365-0.1.0/PKG-INFO +197 -0
- pybc365-0.1.0/README.md +170 -0
- pybc365-0.1.0/pyproject.toml +184 -0
- pybc365-0.1.0/pyproject.toml.orig +199 -0
- pybc365-0.1.0/src/pybc365/__init__.py +83 -0
- pybc365-0.1.0/src/pybc365/_reader.py +199 -0
- pybc365-0.1.0/src/pybc365/_surface.py +111 -0
- pybc365-0.1.0/src/pybc365/_transport.py +140 -0
- pybc365-0.1.0/src/pybc365/_version.py +9 -0
- pybc365-0.1.0/src/pybc365/client.py +316 -0
- pybc365-0.1.0/src/pybc365/errors.py +167 -0
- pybc365-0.1.0/src/pybc365/filters.py +811 -0
- pybc365-0.1.0/src/pybc365/py.typed +0 -0
- pybc365-0.1.0/src/pybc365/query.py +393 -0
- pybc365-0.1.0/src/pybc365/retry.py +87 -0
pybc365-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Konspec - FPA
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
pybc365-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pybc365
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A modern, fully typed Python client for Microsoft Dynamics 365 Business Central.
|
|
5
|
+
Keywords: business-central,dynamics-365,microsoft-dynamics,erp,api,odata,python
|
|
6
|
+
Author: Akshay Prabhu
|
|
7
|
+
Author-email: Akshay Prabhu <akshay.prabhu@konspec.com>
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Classifier: Development Status :: 2 - Pre-Alpha
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
18
|
+
Classifier: Topic :: Office/Business :: Financial
|
|
19
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
20
|
+
Classifier: Typing :: Typed
|
|
21
|
+
Requires-Dist: httpx>=0.28.1
|
|
22
|
+
Requires-Python: >=3.12
|
|
23
|
+
Project-URL: Homepage, https://github.com/konfpa/pybc365
|
|
24
|
+
Project-URL: Repository, https://github.com/konfpa/pybc365
|
|
25
|
+
Project-URL: Issues, https://github.com/konfpa/pybc365/issues
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
|
|
28
|
+
# pybc365
|
|
29
|
+
|
|
30
|
+
A modern, fully typed Python client for Microsoft Dynamics 365 Business Central.
|
|
31
|
+
|
|
32
|
+
[](https://github.com/konfpa/pybc365/actions/workflows/ci.yml)
|
|
33
|
+
[](https://pypi.org/project/pybc365/)
|
|
34
|
+
[](https://pypi.org/project/pybc365/)
|
|
35
|
+
[](LICENSE)
|
|
36
|
+
[](https://github.com/astral-sh/ruff)
|
|
37
|
+
[](https://mypy-lang.org/)
|
|
38
|
+
|
|
39
|
+
## What is pybc365?
|
|
40
|
+
|
|
41
|
+
`pybc365` is a Python library for talking to Microsoft Dynamics 365
|
|
42
|
+
Business Central. It's meant to be a dependable building block for the
|
|
43
|
+
kinds of code that need to move data in and out of BC: applications,
|
|
44
|
+
automation scripts, ETL/data pipelines, and backend services.
|
|
45
|
+
|
|
46
|
+
The library is generic by design: it does not assume anything about a
|
|
47
|
+
particular Business Central tenant, company, or set of custom entities.
|
|
48
|
+
|
|
49
|
+
## Why pybc365?
|
|
50
|
+
|
|
51
|
+
- **Python-friendly** - designed to feel natural in Python code, not like
|
|
52
|
+
a thin wrapper around BC's OData/REST conventions.
|
|
53
|
+
- **Fully typed** - the whole library ships type annotations and a
|
|
54
|
+
`py.typed` marker, so type checkers understand it out of the box.
|
|
55
|
+
- **Explicit over magical** - no hidden metaclass tricks or implicit
|
|
56
|
+
global state; what the code does is visible in the code.
|
|
57
|
+
- **Minimal assumptions** - no baked-in entities, companies, or
|
|
58
|
+
environment configuration.
|
|
59
|
+
- **Composable and minimal dependencies** - suitable for use as
|
|
60
|
+
infrastructure inside larger systems.
|
|
61
|
+
|
|
62
|
+
`httpx` is the only runtime dependency. See
|
|
63
|
+
[Project status](#project-status) for what v0.1 covers.
|
|
64
|
+
|
|
65
|
+
## Installation
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
pip install pybc365
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
or, with uv:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
uv add pybc365
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
`pybc365` itself does not require uv; it's a normal PyPI package.
|
|
78
|
+
|
|
79
|
+
## Quick start
|
|
80
|
+
|
|
81
|
+
```python
|
|
82
|
+
import httpx
|
|
83
|
+
|
|
84
|
+
from pybc365 import Client, F, desc
|
|
85
|
+
|
|
86
|
+
with Client(
|
|
87
|
+
base_url="https://bc.example.com/BC240",
|
|
88
|
+
company="CRONUS International Ltd.",
|
|
89
|
+
auth=httpx.BasicAuth("webservice", "hunter2"),
|
|
90
|
+
) as client:
|
|
91
|
+
customers = (
|
|
92
|
+
client.service("Customers")
|
|
93
|
+
.filter(F.Name.startswith("Contoso"), F.Blocked == "")
|
|
94
|
+
.select("No", "Name", "Balance")
|
|
95
|
+
.order_by(desc("Balance"))
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
print(customers.count())
|
|
99
|
+
|
|
100
|
+
for row in customers:
|
|
101
|
+
print(row["No"], row["Name"], row["Balance"])
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
`base_url` is the server root, stopping **before** the `ODataV4` segment.
|
|
105
|
+
Construction sends no request; the first request goes out when the loop asks
|
|
106
|
+
for its first row.
|
|
107
|
+
|
|
108
|
+
Reading amounts? Pass `parse_float=Decimal`. The default `float` loses the
|
|
109
|
+
digits of an `Edm.Decimal` before your code ever sees them. See
|
|
110
|
+
[Types on the wire](./docs/types-on-the-wire.md).
|
|
111
|
+
|
|
112
|
+
If `Client` collides with `httpx.Client` in your module, import the package
|
|
113
|
+
instead and write `pybc365.Client`.
|
|
114
|
+
|
|
115
|
+
## Documentation
|
|
116
|
+
|
|
117
|
+
The [documentation](./docs/index.md) ships in this repository.
|
|
118
|
+
|
|
119
|
+
| Page | Answers |
|
|
120
|
+
|---|---|
|
|
121
|
+
| [Getting started](./docs/getting-started.md) | How do I install it and read my first rows? |
|
|
122
|
+
| [Authentication](./docs/authentication.md) | Which auth recipe is tested, and against what? |
|
|
123
|
+
| [Queries](./docs/queries.md) | How do I select, order, page and count? |
|
|
124
|
+
| [Filters](./docs/filters.md) | What literal does my value become, and what does Business Central refuse? |
|
|
125
|
+
| [Types on the wire](./docs/types-on-the-wire.md) | What Python type will this value be? |
|
|
126
|
+
| [Errors](./docs/errors.md) | Which exception is this, and what caused it? |
|
|
127
|
+
| [Not shipped: the REST surface](./docs/rest-surface.md) | Why is there no `/api/v2.0` client? |
|
|
128
|
+
| [API reference](./docs/api.md) | The full signature of every public name. |
|
|
129
|
+
|
|
130
|
+
## Project status
|
|
131
|
+
|
|
132
|
+
**v0.1: sync, fully typed, read-only.** The library reads published web
|
|
133
|
+
services (OData V4) from one company on one server, with filters, selection,
|
|
134
|
+
ordering, server-driven paging, retry and one exception hierarchy.
|
|
135
|
+
|
|
136
|
+
Not in v0.1: create, update and delete; an async client; the REST API
|
|
137
|
+
(`/api/v2.0`); `$expand`; and any fetch of `$metadata`. `AsyncClient` is the
|
|
138
|
+
reserved name for the async client, and no such class ships today.
|
|
139
|
+
|
|
140
|
+
"Fully typed" means the library checks the **call shape** and nothing about the
|
|
141
|
+
**data**. A misspelled web service, field, projection or ordering key all pass a
|
|
142
|
+
strict `mypy` check with `dict[str, Any]` rows. A `row=` converter is the only
|
|
143
|
+
thing that closes that gap.
|
|
144
|
+
|
|
145
|
+
Every Business Central fact in this documentation is an observation of **BC
|
|
146
|
+
22.2 on-premises**, never a Business Central guarantee.
|
|
147
|
+
|
|
148
|
+
`pybc365` is not affiliated with or endorsed by Microsoft.
|
|
149
|
+
|
|
150
|
+
## Design principles
|
|
151
|
+
|
|
152
|
+
- Typed by default, everywhere in the public API.
|
|
153
|
+
- Explicit over magical.
|
|
154
|
+
- Minimal runtime dependencies.
|
|
155
|
+
- Endpoint-agnostic: no assumptions about specific BC entities or setups.
|
|
156
|
+
- Composable pieces over one large client object.
|
|
157
|
+
- Predictable, deliberately designed public APIs.
|
|
158
|
+
- Testable architecture, with behavior-focused tests.
|
|
159
|
+
|
|
160
|
+
## Development
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
git clone https://github.com/konfpa/pybc365.git
|
|
164
|
+
cd pybc365
|
|
165
|
+
uv sync
|
|
166
|
+
uv run prek install
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Common commands:
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
uv run ruff format . # format
|
|
173
|
+
uv run ruff check . # lint
|
|
174
|
+
uv run mypy src scripts tests # type check
|
|
175
|
+
uv run pytest # test (with coverage)
|
|
176
|
+
uv run prek run --all-files # all pre-commit hooks
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
See [`AGENTS.md`](./AGENTS.md) for the fuller set of engineering
|
|
180
|
+
principles and quality expectations this project follows.
|
|
181
|
+
|
|
182
|
+
## Contributing
|
|
183
|
+
|
|
184
|
+
Contributions are welcome. Please read [`AGENTS.md`](./AGENTS.md) for the
|
|
185
|
+
project's engineering principles before opening a pull request, and see
|
|
186
|
+
[`CONTRIBUTING.md`](./CONTRIBUTING.md) for the contribution workflow.
|
|
187
|
+
|
|
188
|
+
## Security
|
|
189
|
+
|
|
190
|
+
See [`SECURITY.md`](./SECURITY.md) for how to report a vulnerability.
|
|
191
|
+
|
|
192
|
+
## License
|
|
193
|
+
|
|
194
|
+
Licensed under the [MIT License](./LICENSE).
|
|
195
|
+
|
|
196
|
+
`pybc365` is an independent open-source project and is not affiliated
|
|
197
|
+
with or endorsed by Microsoft.
|
pybc365-0.1.0/README.md
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# pybc365
|
|
2
|
+
|
|
3
|
+
A modern, fully typed Python client for Microsoft Dynamics 365 Business Central.
|
|
4
|
+
|
|
5
|
+
[](https://github.com/konfpa/pybc365/actions/workflows/ci.yml)
|
|
6
|
+
[](https://pypi.org/project/pybc365/)
|
|
7
|
+
[](https://pypi.org/project/pybc365/)
|
|
8
|
+
[](LICENSE)
|
|
9
|
+
[](https://github.com/astral-sh/ruff)
|
|
10
|
+
[](https://mypy-lang.org/)
|
|
11
|
+
|
|
12
|
+
## What is pybc365?
|
|
13
|
+
|
|
14
|
+
`pybc365` is a Python library for talking to Microsoft Dynamics 365
|
|
15
|
+
Business Central. It's meant to be a dependable building block for the
|
|
16
|
+
kinds of code that need to move data in and out of BC: applications,
|
|
17
|
+
automation scripts, ETL/data pipelines, and backend services.
|
|
18
|
+
|
|
19
|
+
The library is generic by design: it does not assume anything about a
|
|
20
|
+
particular Business Central tenant, company, or set of custom entities.
|
|
21
|
+
|
|
22
|
+
## Why pybc365?
|
|
23
|
+
|
|
24
|
+
- **Python-friendly** - designed to feel natural in Python code, not like
|
|
25
|
+
a thin wrapper around BC's OData/REST conventions.
|
|
26
|
+
- **Fully typed** - the whole library ships type annotations and a
|
|
27
|
+
`py.typed` marker, so type checkers understand it out of the box.
|
|
28
|
+
- **Explicit over magical** - no hidden metaclass tricks or implicit
|
|
29
|
+
global state; what the code does is visible in the code.
|
|
30
|
+
- **Minimal assumptions** - no baked-in entities, companies, or
|
|
31
|
+
environment configuration.
|
|
32
|
+
- **Composable and minimal dependencies** - suitable for use as
|
|
33
|
+
infrastructure inside larger systems.
|
|
34
|
+
|
|
35
|
+
`httpx` is the only runtime dependency. See
|
|
36
|
+
[Project status](#project-status) for what v0.1 covers.
|
|
37
|
+
|
|
38
|
+
## Installation
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
pip install pybc365
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
or, with uv:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
uv add pybc365
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
`pybc365` itself does not require uv; it's a normal PyPI package.
|
|
51
|
+
|
|
52
|
+
## Quick start
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
import httpx
|
|
56
|
+
|
|
57
|
+
from pybc365 import Client, F, desc
|
|
58
|
+
|
|
59
|
+
with Client(
|
|
60
|
+
base_url="https://bc.example.com/BC240",
|
|
61
|
+
company="CRONUS International Ltd.",
|
|
62
|
+
auth=httpx.BasicAuth("webservice", "hunter2"),
|
|
63
|
+
) as client:
|
|
64
|
+
customers = (
|
|
65
|
+
client.service("Customers")
|
|
66
|
+
.filter(F.Name.startswith("Contoso"), F.Blocked == "")
|
|
67
|
+
.select("No", "Name", "Balance")
|
|
68
|
+
.order_by(desc("Balance"))
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
print(customers.count())
|
|
72
|
+
|
|
73
|
+
for row in customers:
|
|
74
|
+
print(row["No"], row["Name"], row["Balance"])
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
`base_url` is the server root, stopping **before** the `ODataV4` segment.
|
|
78
|
+
Construction sends no request; the first request goes out when the loop asks
|
|
79
|
+
for its first row.
|
|
80
|
+
|
|
81
|
+
Reading amounts? Pass `parse_float=Decimal`. The default `float` loses the
|
|
82
|
+
digits of an `Edm.Decimal` before your code ever sees them. See
|
|
83
|
+
[Types on the wire](./docs/types-on-the-wire.md).
|
|
84
|
+
|
|
85
|
+
If `Client` collides with `httpx.Client` in your module, import the package
|
|
86
|
+
instead and write `pybc365.Client`.
|
|
87
|
+
|
|
88
|
+
## Documentation
|
|
89
|
+
|
|
90
|
+
The [documentation](./docs/index.md) ships in this repository.
|
|
91
|
+
|
|
92
|
+
| Page | Answers |
|
|
93
|
+
|---|---|
|
|
94
|
+
| [Getting started](./docs/getting-started.md) | How do I install it and read my first rows? |
|
|
95
|
+
| [Authentication](./docs/authentication.md) | Which auth recipe is tested, and against what? |
|
|
96
|
+
| [Queries](./docs/queries.md) | How do I select, order, page and count? |
|
|
97
|
+
| [Filters](./docs/filters.md) | What literal does my value become, and what does Business Central refuse? |
|
|
98
|
+
| [Types on the wire](./docs/types-on-the-wire.md) | What Python type will this value be? |
|
|
99
|
+
| [Errors](./docs/errors.md) | Which exception is this, and what caused it? |
|
|
100
|
+
| [Not shipped: the REST surface](./docs/rest-surface.md) | Why is there no `/api/v2.0` client? |
|
|
101
|
+
| [API reference](./docs/api.md) | The full signature of every public name. |
|
|
102
|
+
|
|
103
|
+
## Project status
|
|
104
|
+
|
|
105
|
+
**v0.1: sync, fully typed, read-only.** The library reads published web
|
|
106
|
+
services (OData V4) from one company on one server, with filters, selection,
|
|
107
|
+
ordering, server-driven paging, retry and one exception hierarchy.
|
|
108
|
+
|
|
109
|
+
Not in v0.1: create, update and delete; an async client; the REST API
|
|
110
|
+
(`/api/v2.0`); `$expand`; and any fetch of `$metadata`. `AsyncClient` is the
|
|
111
|
+
reserved name for the async client, and no such class ships today.
|
|
112
|
+
|
|
113
|
+
"Fully typed" means the library checks the **call shape** and nothing about the
|
|
114
|
+
**data**. A misspelled web service, field, projection or ordering key all pass a
|
|
115
|
+
strict `mypy` check with `dict[str, Any]` rows. A `row=` converter is the only
|
|
116
|
+
thing that closes that gap.
|
|
117
|
+
|
|
118
|
+
Every Business Central fact in this documentation is an observation of **BC
|
|
119
|
+
22.2 on-premises**, never a Business Central guarantee.
|
|
120
|
+
|
|
121
|
+
`pybc365` is not affiliated with or endorsed by Microsoft.
|
|
122
|
+
|
|
123
|
+
## Design principles
|
|
124
|
+
|
|
125
|
+
- Typed by default, everywhere in the public API.
|
|
126
|
+
- Explicit over magical.
|
|
127
|
+
- Minimal runtime dependencies.
|
|
128
|
+
- Endpoint-agnostic: no assumptions about specific BC entities or setups.
|
|
129
|
+
- Composable pieces over one large client object.
|
|
130
|
+
- Predictable, deliberately designed public APIs.
|
|
131
|
+
- Testable architecture, with behavior-focused tests.
|
|
132
|
+
|
|
133
|
+
## Development
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
git clone https://github.com/konfpa/pybc365.git
|
|
137
|
+
cd pybc365
|
|
138
|
+
uv sync
|
|
139
|
+
uv run prek install
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Common commands:
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
uv run ruff format . # format
|
|
146
|
+
uv run ruff check . # lint
|
|
147
|
+
uv run mypy src scripts tests # type check
|
|
148
|
+
uv run pytest # test (with coverage)
|
|
149
|
+
uv run prek run --all-files # all pre-commit hooks
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
See [`AGENTS.md`](./AGENTS.md) for the fuller set of engineering
|
|
153
|
+
principles and quality expectations this project follows.
|
|
154
|
+
|
|
155
|
+
## Contributing
|
|
156
|
+
|
|
157
|
+
Contributions are welcome. Please read [`AGENTS.md`](./AGENTS.md) for the
|
|
158
|
+
project's engineering principles before opening a pull request, and see
|
|
159
|
+
[`CONTRIBUTING.md`](./CONTRIBUTING.md) for the contribution workflow.
|
|
160
|
+
|
|
161
|
+
## Security
|
|
162
|
+
|
|
163
|
+
See [`SECURITY.md`](./SECURITY.md) for how to report a vulnerability.
|
|
164
|
+
|
|
165
|
+
## License
|
|
166
|
+
|
|
167
|
+
Licensed under the [MIT License](./LICENSE).
|
|
168
|
+
|
|
169
|
+
`pybc365` is an independent open-source project and is not affiliated
|
|
170
|
+
with or endorsed by Microsoft.
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "pybc365"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "A modern, fully typed Python client for Microsoft Dynamics 365 Business Central."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
license = "MIT"
|
|
7
|
+
license-files = ["LICENSE"]
|
|
8
|
+
requires-python = ">=3.12"
|
|
9
|
+
keywords = [
|
|
10
|
+
"business-central",
|
|
11
|
+
"dynamics-365",
|
|
12
|
+
"microsoft-dynamics",
|
|
13
|
+
"erp",
|
|
14
|
+
"api",
|
|
15
|
+
"odata",
|
|
16
|
+
"python",
|
|
17
|
+
]
|
|
18
|
+
classifiers = [
|
|
19
|
+
"Development Status :: 2 - Pre-Alpha",
|
|
20
|
+
"Intended Audience :: Developers",
|
|
21
|
+
"Operating System :: OS Independent",
|
|
22
|
+
"Programming Language :: Python :: 3",
|
|
23
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
24
|
+
"Programming Language :: Python :: 3.12",
|
|
25
|
+
"Programming Language :: Python :: 3.13",
|
|
26
|
+
"Programming Language :: Python :: 3.14",
|
|
27
|
+
"Topic :: Office/Business :: Financial",
|
|
28
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
29
|
+
"Typing :: Typed",
|
|
30
|
+
]
|
|
31
|
+
dependencies = ["httpx>=0.28.1"]
|
|
32
|
+
|
|
33
|
+
[[project.authors]]
|
|
34
|
+
name = "Akshay Prabhu"
|
|
35
|
+
email = "akshay.prabhu@konspec.com"
|
|
36
|
+
|
|
37
|
+
[project.urls]
|
|
38
|
+
Homepage = "https://github.com/konfpa/pybc365"
|
|
39
|
+
Repository = "https://github.com/konfpa/pybc365"
|
|
40
|
+
Issues = "https://github.com/konfpa/pybc365/issues"
|
|
41
|
+
|
|
42
|
+
[build-system]
|
|
43
|
+
requires = ["uv_build>=0.12.6,<0.13.0"]
|
|
44
|
+
build-backend = "uv_build"
|
|
45
|
+
|
|
46
|
+
[dependency-groups]
|
|
47
|
+
dev = [
|
|
48
|
+
"httpx-ntlm>=1.4.0",
|
|
49
|
+
"mypy>=2.3.1",
|
|
50
|
+
"prek>=0.5.2",
|
|
51
|
+
"pytest>=9.1.1",
|
|
52
|
+
"pytest-cov>=7.1.0",
|
|
53
|
+
"ruff>=0.16.6",
|
|
54
|
+
]
|
|
55
|
+
|
|
56
|
+
[tool.ruff]
|
|
57
|
+
target-version = "py312"
|
|
58
|
+
src = ["src"]
|
|
59
|
+
preview = true
|
|
60
|
+
|
|
61
|
+
[tool.ruff.lint]
|
|
62
|
+
select = [
|
|
63
|
+
"E",
|
|
64
|
+
"W",
|
|
65
|
+
"F",
|
|
66
|
+
"I",
|
|
67
|
+
"N",
|
|
68
|
+
"UP",
|
|
69
|
+
"B",
|
|
70
|
+
"C4",
|
|
71
|
+
"SIM",
|
|
72
|
+
"RET",
|
|
73
|
+
"PTH",
|
|
74
|
+
"ANN",
|
|
75
|
+
"BLE",
|
|
76
|
+
"EM",
|
|
77
|
+
"TRY",
|
|
78
|
+
"RSE",
|
|
79
|
+
"T10",
|
|
80
|
+
"PT",
|
|
81
|
+
"ARG",
|
|
82
|
+
"TID",
|
|
83
|
+
"ISC",
|
|
84
|
+
"PIE",
|
|
85
|
+
"TC",
|
|
86
|
+
"ERA",
|
|
87
|
+
"C90",
|
|
88
|
+
"D",
|
|
89
|
+
"DOC",
|
|
90
|
+
"A",
|
|
91
|
+
"S",
|
|
92
|
+
"FBT",
|
|
93
|
+
"DTZ",
|
|
94
|
+
"LOG",
|
|
95
|
+
"G",
|
|
96
|
+
"INP",
|
|
97
|
+
"SLF",
|
|
98
|
+
"SLOT",
|
|
99
|
+
"PL",
|
|
100
|
+
"PERF",
|
|
101
|
+
"FURB",
|
|
102
|
+
"PGH",
|
|
103
|
+
"EXE",
|
|
104
|
+
"ICN",
|
|
105
|
+
"PYI",
|
|
106
|
+
"ASYNC",
|
|
107
|
+
"T20",
|
|
108
|
+
"YTT",
|
|
109
|
+
"INT",
|
|
110
|
+
"FLY",
|
|
111
|
+
"RUF",
|
|
112
|
+
"multi-line-summary-second-line",
|
|
113
|
+
]
|
|
114
|
+
ignore = [
|
|
115
|
+
"single-line-implicit-string-concatenation",
|
|
116
|
+
"raise-vanilla-args",
|
|
117
|
+
"docstring-extraneous-exception",
|
|
118
|
+
"multi-line-summary-first-line",
|
|
119
|
+
]
|
|
120
|
+
|
|
121
|
+
[tool.ruff.lint.per-file-ignores]
|
|
122
|
+
"scripts/*.py" = ["implicit-namespace-package"]
|
|
123
|
+
"tests/**/*.py" = [
|
|
124
|
+
"ARG",
|
|
125
|
+
"assert",
|
|
126
|
+
"implicit-namespace-package",
|
|
127
|
+
"private-member-access",
|
|
128
|
+
"magic-value-comparison",
|
|
129
|
+
"import-private-name",
|
|
130
|
+
"import-outside-top-level",
|
|
131
|
+
"compare-to-empty-string",
|
|
132
|
+
"float-equality-comparison",
|
|
133
|
+
]
|
|
134
|
+
|
|
135
|
+
[tool.ruff.lint.isort]
|
|
136
|
+
known-first-party = ["pybc365"]
|
|
137
|
+
|
|
138
|
+
[tool.ruff.lint.mccabe]
|
|
139
|
+
max-complexity = 10
|
|
140
|
+
|
|
141
|
+
[tool.ruff.lint.pydocstyle]
|
|
142
|
+
convention = "google"
|
|
143
|
+
|
|
144
|
+
[tool.ruff.lint.pylint]
|
|
145
|
+
max-args = 8
|
|
146
|
+
|
|
147
|
+
[tool.ruff.format]
|
|
148
|
+
docstring-code-format = true
|
|
149
|
+
exclude = ["*.md"]
|
|
150
|
+
|
|
151
|
+
[tool.mypy]
|
|
152
|
+
python_version = "3.12"
|
|
153
|
+
strict = true
|
|
154
|
+
warn_unreachable = true
|
|
155
|
+
enable_error_code = [
|
|
156
|
+
"ignore-without-code",
|
|
157
|
+
"redundant-expr",
|
|
158
|
+
"possibly-undefined",
|
|
159
|
+
]
|
|
160
|
+
|
|
161
|
+
[[tool.mypy.overrides]]
|
|
162
|
+
module = ["httpx_ntlm.*"]
|
|
163
|
+
ignore_missing_imports = true
|
|
164
|
+
|
|
165
|
+
[tool.pytest.ini_options]
|
|
166
|
+
addopts = [
|
|
167
|
+
"--cov=pybc365",
|
|
168
|
+
"--cov-report=term-missing",
|
|
169
|
+
"--cov-fail-under=95",
|
|
170
|
+
"-m",
|
|
171
|
+
"not live",
|
|
172
|
+
]
|
|
173
|
+
testpaths = ["tests"]
|
|
174
|
+
markers = ["live: reads a real Business Central instance. Run with -m live."]
|
|
175
|
+
|
|
176
|
+
[tool.coverage.run]
|
|
177
|
+
source = ["pybc365"]
|
|
178
|
+
branch = true
|
|
179
|
+
|
|
180
|
+
[tool.coverage.report]
|
|
181
|
+
exclude_lines = [
|
|
182
|
+
"pragma: no cover",
|
|
183
|
+
"if TYPE_CHECKING:",
|
|
184
|
+
]
|