Skip to content

Commit

Permalink
Merge pull request #6 from j4asper/v1
Browse files Browse the repository at this point in the history
Merge v1.0.0 update
  • Loading branch information
j4asper authored Sep 7, 2023
2 parents 1801411 + 21b99d0 commit fce01f6
Show file tree
Hide file tree
Showing 19 changed files with 334 additions and 692 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -129,4 +129,6 @@ dmypy.json
.pyre/

# VS Code config folder
.vscode
.vscode

.idea
36 changes: 23 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,68 +4,78 @@
[![GitHub](https://img.shields.io/github/license/j4asper/dmr.py?style=for-the-badge)](https://github.com/j4asper/dmr.py/blob/main/LICENSE)
[![BuyMeACoffee](https://img.shields.io/badge/Buy%20Me%20a%20Coffee-ffdd00?style=for-the-badge&logo=buy-me-a-coffee&logoColor=black)](https://www.buymeacoffee.com/jazper 'Click here to donate')

# dmr.py
# dmr.py

You will no longer need an exspensive API for danish license plate lookups with dmr.py, this tool scrapes the [danish vehicle registry](https://motorregister.skat.dk/dmr-kerne/koeretoejdetaljer/visKoeretoej 'motorregister.skat.dk') directly and returns the data for you to use in your application. Be aware, that because of skat.dk's very slow database lookups, it could take about 3-4 seconds before getting a response.

## Installation:
## Installation:

Install with pip

```console
python -m pip install dmr.py
```

If you want to install the additional speedup packages, you can use the command below. These speedup packages is only for the async part of this library. If you are only using the synchronous part, then this is unnecessary.

```console
python -m pip install dmr.py[speed]
```


Install current code from this repo, you will need to have git installed in order to do this. The code in the repo might not match the current release, if you experience errors you should switch back the the latest release.

```console
python -m pip install git+https://github.com/j4asper/dmr.py
```


## Example

**Synchronously**
**Synchronously**

```python
from dmr import DMR

license_plate = "cw87553"

# Get DMR object with data
vehicle = DMR(license_plate).get_by_plate()
# Get Vehicle object with data
vehicle = DMR.get_by_plate(license_plate)

print("The vehicle make is:", vehicle.make)
# The vehicle make is: Suzuki
```

---

**Asynchronously**

```python
from dmr import DMR

license_plate = "cw87553"

# Get DMR object with data
vehicle = await DMR(license_plate).get_by_plate_async()
vehicle = await DMR.get_by_plate_async(license_plate)

print("The vehicle make is:", vehicle.make)
# The vehicle make is: Suzuki
```

**All attributes to the DMR() object [can be viewed in the Wiki](https://github.com/j4asper/dmr.py/wiki/DMR-Attributes 'Click here to go to the Wiki')**
**All attributes to the Vehicle object [can be viewed in the Wiki](https://github.com/j4asper/dmr.py/wiki/DMR-Attributes 'Click here to go to the Wiki')**

## Contributing:
I would be more than happy if those who know how to make pull requests, contribute with code! Sometimes XPaths may not match with the ones on the [danish vehicle register](https://motorregister.skat.dk/dmr-kerne/koeretoejdetaljer/visKoeretoej 'motorregister.skat.dk'), if that's the case, then you can either make a pull request with XPath fixes or make an issue saying that the XPaths are wrong, then i will fix it. XPaths are kept in [this file](https://github.com/j4asper/dmr.py/blob/main/dmr/utils/xpaths.py).

I would be more than happy if those who know how to make pull requests, contribute with code! Sometimes XPaths may not match with the ones on the [danish vehicle register](https://motorregister.skat.dk/dmr-kerne/koeretoejdetaljer/visKoeretoej 'motorregister.skat.dk'), if that's the case, then you can either make a pull request with XPath fixes or make an issue saying that the XPaths are wrong, then I will fix it. XPaths are kept in [this file](https://github.com/j4asper/dmr.py/blob/main/dmr/utils/xpaths.py).

## ToDo:
- [x] Add from_dict and to_dict functions.

- [x] Add documentation with all possible values.
- [ ] Scrape more parts of the DMR site to get even more data.
- [x] Add more broad tests with different types of cars or bikes.

## Issue we can't do anything about.
If you have used this tool, you might notice that it is slow AF. That is probably due to our government using multiple 80-100 GB XML files as the databse for all vehicles in Denmark. It roughly takes about 3 seconds to do a lookup on the DMR site. Caching is __highly__ recommended!
## Issue we can't do anything about.

If you have used this tool, you might notice that it's very slow. That is probably due to our government using multiple 80-100 GB XML files as the databse for all vehicles in Denmark. It roughly takes about 3 seconds to do a lookup on the DMR site. Caching is __highly__ recommended!

## License Plates for testing:

You can use all the license plates listed in [**This file**](https://github.com/j4asper/dmr.py/blob/main/license_plates.txt 'Click here') for testing. If a license plate turns out to be invalid, please remove it and make a PR, or create an issue stating this.
9 changes: 7 additions & 2 deletions dmr/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@
from .dmr_model import DMR
from .insurance_model import Insurance
from .models.insurance import Insurance
from .models.vehicle import Vehicle
from .models.propulsion_type import PropulsionType
from .models.vehicle_type import VehicleType
from .models.body_type import BodyType
from .models.use_type import UseType
from dmr.dmr import DMR
78 changes: 78 additions & 0 deletions dmr/dmr.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
from __future__ import annotations
from typing import Optional
from dmr.models.vehicle import Vehicle
from re import search, RegexFlag
from dmr.utils import (
scrape_async,
scrape,
errors,
)


class DMR:

@classmethod
def validate_license_plate(cls, license_plate: str) -> bool:
"""Checks if the given string can be a license plate, this check is also run prior to the webscraping.
Args:
license_plate (str): The license plate to check
Returns:
bool: Returns True if the given license plate could be a license plate, or False if not.
"""

match = search(r"^[A-Z0-9]{2,7}$", license_plate.upper())
if match:
return True
else:
return False


@classmethod
def get_by_plate(cls, license_plate: str) -> Optional[Vehicle]:
"""Get data from DMR by license plate.
Args:
license_plate (str): The license plate to look up. Not required if license plate was passed into the DMR object.
Raises:
InvalidLicensePlate: Invalid license plate was given
Returns:
DMR: DMR object is returned, check https://github.com/j4asper/dmr.py/wiki for more information.
"""

if not cls.validate_license_plate(license_plate):
raise errors.InvalidLicensePlate("Invalid license plate. license plate length should be between 2 and 7 letters and/or digits.")

data = scrape(license_plate=license_plate)
if data:
return Vehicle(**data)
else:
return None


@classmethod
async def get_by_plate_async(cls, license_plate: str):
"""Get data from DMR asynchronously by license plate.
Args:
license_plate (str): The license plate to look up.
Raises:
InvalidLicensePlate: Invalid license plate was given
Returns:
DMR: DMR object is returned, check https://github.com/j4asper/dmr.py/wiki for more information.
"""

if not cls.validate_license_plate(license_plate):
raise errors.InvalidLicensePlate(
"Invalid license plate. license plate length should be between 2 and 7 letters and/or digits.")

data = await scrape_async(license_plate=license_plate)
if data:
return Vehicle(**data)
else:
return None
Loading

0 comments on commit fce01f6

Please sign in to comment.