Skip to content
Merged
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: 19 additions & 0 deletions HACKING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Hacking

This document provides guides on how to develop and maintain the pyodata Python
module.

## Tips & tricks

If you want to avoid creating pull requests that fail on lint errors but you
always forgot to run `make check`, create the pre-commit file in the director
.git/hooks with the following content:

```bash
#!/bin/sh

make check
```

Do not forget to run `chmod +x .git/hooks/pre-commit` to make the hook script
executable.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.

Copyright 2018 SAP®
Copyright 2019 SAP®

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
1 change: 1 addition & 0 deletions NOTICE
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Copyright (c) 2019 SAP SE or an SAP affiliate company. All rights reserved.
231 changes: 34 additions & 197 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,212 +1,58 @@
# python-pyodata
# Python OData Client - pyodata

Enterprise-ready Python OData client
Python OData client which provides comfortable Python agnostic
way for communication with OData services.

## Requirements

- Python 3.6

## Usage

### Get the service

```python
import requests
import pyodata
The goal of this Python module is to hide all OData protocol implementation
details.

SERVICE_URL = 'http://services.odata.org/V2/Northwind/Northwind.svc/'

# Create instance of OData client
client = pyodata.Client(SERVICE_URL, requests.Session())
```

### Get one entity identified by its key value

```python
# Get employee identified by 1 and print employee first name
employee1 = client.entity_sets.Employees.get_entity(1).execute()
print employee1.FirstName
```
## Requirements

### Get one entity identified by its key value which is not scalar
- [Python >= 3.6](https://www.python.org/downloads/release/python-368/)

```python
# Get number of orderd units in the order identified by ProductID 42 and OrderID 10248.
order = client.entity_sets.Order_Details.get_entity(OrderID=10248, ProductID=42).execute()
print(order.Quantity)
```
## Download and Installation

### Get all entities of an entity set

```python
You can make use of [pip](https://packaging.python.org/tutorials/installing-packages/#installing-from-vcs)
to install the pyodata module automatically:

# Print unique identification (Id) and last name of all cemployees
employees = client.entity_sets.Employees.get_entities().select('EmployeeID,LasttName').execute()
for employee in employees:
print(employee.EmployeeID, employee.LastName)
```bash
pip install -e git+https://github.com/SAP/python-pyodata.git
```

### Get entities matching a filter
## Configuration

```python
# Print unique identification (Id) of all employees with name John Smith
smith_employees_request = client.entity_sets.Employees.get_entities()
smith_employees_request = smith_employees_request.filter("FirstName eq 'John' and LastName eq 'Smith'")
for smith in smith_employees.execute():
print(smith.EmployeeID)
```
You can start building your OData projects straight away after installing the
Python module without any additional configuration steps needed.

### Get entities matching a filter in more Pythonic way
## Limitations

```python
from pyodata.v2.service import GetEntitySetFilter
There have been no limitations discovered yet.

# Print unique identification (Id) of all employees with name John Smith
smith_employees_request = client.entity_sets.Employees.get_entities()
smith_employees_request = smith_employees_request.filter(GetEntitySetFilter.and_(
smith_employees_request.FirstName == 'Jonh',
smith_employees_request.LastName == 'Smith'))
for smith in smith_employees_request.execute():
print(smith.EmployeeID)
```
## Known Issues

### Creating entity
There are no known issues at this time.

You need to use the method set which accepts key value parameters:
## How to obtain support

```python
employee_data = {
'FirstName': 'Mark',
'LastName': 'Goody',
'Address': {
'HouseNumber': 42,
'Street': 'Paradise',
'City': 'Heaven'
}
}
We accept bug reports, feature requests, questions and comments via [GitHub issues](https://github.com/SAP/python-pyodata/issues)

create_request = client.entity_sets.Employees.create_entity()
create_request.set(**employee_data)

new_employee_entity = create_request.execute()
```
## Usage

or you can do it explicitly:
The only thing you need to do is to import the _pyodata_ Python module.

```python
create_request = client.entity_sets.Employees.create_entity()
create_request.set(
FirstName='Mark',
LastName='Goody',
Address={
'HouseNumber': 42,
'Street': 'Paradise',
'City': 'Heaven'
}
)

new_employee_entity = request.execute()
```


### Batch requests

Example of batch request that contains 3 simple entity queries
```
client = pyodata.Client(SERVICE_URL, requests.Session())

batch = client.create_batch()

batch.add_request(client.entity_sets.Employees.get_entity(108))
batch.add_request(client.entity_sets.Employees.get_entity(234))
batch.add_request(client.entity_sets.Employees.get_entity(23))

response = batch.execute()
import requests
import pyodata

print(response[0].EmployeeID, response[0].LastName)
print(response[1].EmployeeID, response[1].LastName)
print(response[1].EmployeeID, response[1].LastName)
```
SERVICE_URL = 'http://services.odata.org/V2/Northwind/Northwind.svc/'

Example of batch request that contains simple entity query as well
as changest consisting of two requests for entity modification
```
# Create instance of OData client
client = pyodata.Client(SERVICE_URL, requests.Session())

batch = client.create_batch()

batch.add_request(client.entity_sets.Employees.get_entity(108))

changeset = client.create_changeset()

changeset.add_request(client.entity_sets.Employees.update_entity(45).set(LastName='Douglas'))

batch.add_request(changeset)

response = batch.execute()

print(response[0].EmployeeID, response[0].LastName)
```

### Calling a function import
Find more sophisticated examples in the [USAGE](USAGE.md) section.

```python
products = client.functions.GetProductsByRating.parameter('rating', 16).execute()
for prod in products:
print(prod)
```

## Error handling

PyOData returns HttpError when the response code does not match the expected
code.

In the case you know the implementation of back-end part and you want to show
accurate errors reported by your service, you can replace HttpError by your
sub-class HttpError by assigning your type into the class member VendorType of
the class HttpError.

```python
from pyodata.exceptions import HttpError


class MyHttpError(HttpError):

def __init__(self, message, response):
super(MyHttpError, self).__init__('Better message', response)


HttpError.VendorType = MyHttpError
```

The class ```pyodata.vendor.SAP.BusinessGatewayError``` is an example of such
an HTTP error handling.

## Metadata tests

By default, the client makes sure that references to properties, entities and
entity sets are pointing to existing elements.

The most often problem that we had to deal with was an invalid ValueList annotion
pointing to a non-existing property.


### Property has this label

```python

assert client.schema.entity_type('Customer').proprty('CustomerID').label == 'Identifier'
```

### Property has a value helper

```python

assert client.schema.entity_type('Customer').proprty('City').value_helper is not None
```


# Contributing
## Contributing

Before contributing, please, make yourself familiar with git. You can [try git
online](https://try.github.io/). Things would be easier for all of us if you do
Expand All @@ -222,7 +68,7 @@ negative decisions - i.e. why you decided to not do particular things. Please
bare in mind that other developers might not understand what the original
problem was.

## Full example
### Full example

Here's an example workflow for a project `PyOData` hosted on Github
Your username is `yourname` and you're submitting a basic bugfix or feature.
Expand All @@ -243,17 +89,8 @@ Your username is `yourname` and you're submitting a basic bugfix or feature.
* Hit 'submit'! And please be patient - the maintainers will get to you when
they can.

## Tips & tricks

If you want to avoid creating pull requests that fail on lint errors but you
always forgot to run `make check`, create the pre-commit file in the director
.git/hooks with the following content:

```bash
#!/bin/sh

make check
```
## License

Do not forget to run `chmod +x .git/hooks/pre-commit` to make the hook script
executable.
Copyright (c) 2019 SAP SE or an SAP affiliate company. All rights reserved.
This file is licensed under the Apache Software License, v. 2 except as noted
otherwise in [the LICENSE file](LICENSE)
Loading