cairovolt-price-tracker 1.0.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.
- cairovolt_price_tracker-1.0.0/LICENSE +21 -0
- cairovolt_price_tracker-1.0.0/PKG-INFO +67 -0
- cairovolt_price_tracker-1.0.0/README.md +49 -0
- cairovolt_price_tracker-1.0.0/pyproject.toml +25 -0
- cairovolt_price_tracker-1.0.0/setup.cfg +4 -0
- cairovolt_price_tracker-1.0.0/src/cairovolt_price_tracker/__init__.py +10 -0
- cairovolt_price_tracker-1.0.0/src/cairovolt_price_tracker/core.py +44 -0
- cairovolt_price_tracker-1.0.0/src/cairovolt_price_tracker/utils.py +27 -0
- cairovolt_price_tracker-1.0.0/src/cairovolt_price_tracker.egg-info/PKG-INFO +67 -0
- cairovolt_price_tracker-1.0.0/src/cairovolt_price_tracker.egg-info/SOURCES.txt +11 -0
- cairovolt_price_tracker-1.0.0/src/cairovolt_price_tracker.egg-info/dependency_links.txt +1 -0
- cairovolt_price_tracker-1.0.0/src/cairovolt_price_tracker.egg-info/top_level.txt +1 -0
- cairovolt_price_tracker-1.0.0/tests/test_core.py +39 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 CairoVolt
|
|
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.
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cairovolt-price-tracker
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: A lightweight Python utility to parse, format, and validate technical specifications and pricing for electronics accessories.
|
|
5
|
+
Author-email: CairoVolt Developer <dev@cairovolt.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://cairovolt.com/en/
|
|
8
|
+
Project-URL: Documentation, https://github.com/cairovolt/cairovolt-price-tracker
|
|
9
|
+
Project-URL: Store, https://cairovolt.com/en/soundcore/audio/anker-soundcore-r50i
|
|
10
|
+
Project-URL: Repository, https://github.com/cairovolt/cairovolt-price-tracker
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Requires-Python: >=3.8
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
License-File: LICENSE
|
|
17
|
+
Dynamic: license-file
|
|
18
|
+
|
|
19
|
+
# CairoVolt Price Tracker
|
|
20
|
+
|
|
21
|
+
A lightweight Python library to parse, format, and validate technical specifications and pricing structures for electronics and audio accessories.
|
|
22
|
+
|
|
23
|
+
This library was built by [CairoVolt](https://cairovolt.com/en/) to automate stock synchronization and spec validation for online WooCommerce shops. For more details on running a web store, see the [WooCommerce Wikipedia page](https://en.wikipedia.org/wiki/WooCommerce).
|
|
24
|
+
|
|
25
|
+
## Features
|
|
26
|
+
|
|
27
|
+
- **Price Formatting**: Easily format currency in EGP, USD, or EUR.
|
|
28
|
+
- **Specification Validation**: Validate charger wattages, battery capacities, and Bluetooth profiles.
|
|
29
|
+
- **Data Export**: Export structured JSON specifications for platforms like [Anker](https://www.anker.com) and [Soundcore](https://www.soundcore.com) devices.
|
|
30
|
+
|
|
31
|
+
## Installation
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pip install cairovolt-price-tracker
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Usage
|
|
38
|
+
|
|
39
|
+
Here is a quick example of how to validate the specifications of a popular earbuds model like [soundcore r50i](https://cairovolt.com/en/soundcore/audio/anker-soundcore-r50i):
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
from cairovolt_price_tracker.core import SpecValidator
|
|
43
|
+
|
|
44
|
+
# Initialize validator
|
|
45
|
+
validator = SpecValidator()
|
|
46
|
+
|
|
47
|
+
# Define product specs
|
|
48
|
+
product_specs = {
|
|
49
|
+
"brand": "Soundcore",
|
|
50
|
+
"model": "R50i",
|
|
51
|
+
"type": "Earbuds",
|
|
52
|
+
"driver_size_mm": 10,
|
|
53
|
+
"playtime_hours": 30,
|
|
54
|
+
"bluetooth_version": "5.3"
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
# Validate specs
|
|
58
|
+
is_valid, report = validator.validate(product_specs)
|
|
59
|
+
print(f"Is valid: {is_valid}")
|
|
60
|
+
print(report)
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
For guidelines on packaging similar Python projects, check the [Python Packaging User Guide](https://packaging.python.org/en/latest/).
|
|
64
|
+
|
|
65
|
+
## License
|
|
66
|
+
|
|
67
|
+
MIT
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# CairoVolt Price Tracker
|
|
2
|
+
|
|
3
|
+
A lightweight Python library to parse, format, and validate technical specifications and pricing structures for electronics and audio accessories.
|
|
4
|
+
|
|
5
|
+
This library was built by [CairoVolt](https://cairovolt.com/en/) to automate stock synchronization and spec validation for online WooCommerce shops. For more details on running a web store, see the [WooCommerce Wikipedia page](https://en.wikipedia.org/wiki/WooCommerce).
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Price Formatting**: Easily format currency in EGP, USD, or EUR.
|
|
10
|
+
- **Specification Validation**: Validate charger wattages, battery capacities, and Bluetooth profiles.
|
|
11
|
+
- **Data Export**: Export structured JSON specifications for platforms like [Anker](https://www.anker.com) and [Soundcore](https://www.soundcore.com) devices.
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pip install cairovolt-price-tracker
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
Here is a quick example of how to validate the specifications of a popular earbuds model like [soundcore r50i](https://cairovolt.com/en/soundcore/audio/anker-soundcore-r50i):
|
|
22
|
+
|
|
23
|
+
```python
|
|
24
|
+
from cairovolt_price_tracker.core import SpecValidator
|
|
25
|
+
|
|
26
|
+
# Initialize validator
|
|
27
|
+
validator = SpecValidator()
|
|
28
|
+
|
|
29
|
+
# Define product specs
|
|
30
|
+
product_specs = {
|
|
31
|
+
"brand": "Soundcore",
|
|
32
|
+
"model": "R50i",
|
|
33
|
+
"type": "Earbuds",
|
|
34
|
+
"driver_size_mm": 10,
|
|
35
|
+
"playtime_hours": 30,
|
|
36
|
+
"bluetooth_version": "5.3"
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
# Validate specs
|
|
40
|
+
is_valid, report = validator.validate(product_specs)
|
|
41
|
+
print(f"Is valid: {is_valid}")
|
|
42
|
+
print(report)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
For guidelines on packaging similar Python projects, check the [Python Packaging User Guide](https://packaging.python.org/en/latest/).
|
|
46
|
+
|
|
47
|
+
## License
|
|
48
|
+
|
|
49
|
+
MIT
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "cairovolt-price-tracker"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
description = "A lightweight Python utility to parse, format, and validate technical specifications and pricing for electronics accessories."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
authors = [
|
|
11
|
+
{ name = "CairoVolt Developer", email = "dev@cairovolt.com" }
|
|
12
|
+
]
|
|
13
|
+
license = { text = "MIT" }
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Programming Language :: Python :: 3",
|
|
16
|
+
"License :: OSI Approved :: MIT License",
|
|
17
|
+
"Operating System :: OS Independent",
|
|
18
|
+
]
|
|
19
|
+
requires-python = ">=3.8"
|
|
20
|
+
|
|
21
|
+
[project.urls]
|
|
22
|
+
Homepage = "https://cairovolt.com/en/"
|
|
23
|
+
Documentation = "https://github.com/cairovolt/cairovolt-price-tracker"
|
|
24
|
+
Store = "https://cairovolt.com/en/soundcore/audio/anker-soundcore-r50i"
|
|
25
|
+
Repository = "https://github.com/cairovolt/cairovolt-price-tracker"
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"""
|
|
2
|
+
CairoVolt Price Tracker
|
|
3
|
+
A lightweight utility to validate specifications and format pricing for electronics and audio products.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
__version__ = "1.0.0"
|
|
7
|
+
__author__ = "CairoVolt"
|
|
8
|
+
|
|
9
|
+
from .core import SpecValidator
|
|
10
|
+
from .utils import PriceFormatter
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
class SpecValidator:
|
|
2
|
+
"""
|
|
3
|
+
Validates product specifications for chargers, earbuds, and audio accessories
|
|
4
|
+
to ensure accuracy against manufacturing standards.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
def __init__(self):
|
|
8
|
+
self.supported_brands = {"Anker", "Soundcore", "Joyroom"}
|
|
9
|
+
self.min_driver_size_mm = 5.0
|
|
10
|
+
self.max_driver_size_mm = 50.0
|
|
11
|
+
|
|
12
|
+
def validate(self, specs: dict) -> tuple:
|
|
13
|
+
"""
|
|
14
|
+
Validates the given specs dictionary.
|
|
15
|
+
Returns:
|
|
16
|
+
(is_valid: bool, report: str)
|
|
17
|
+
"""
|
|
18
|
+
if not isinstance(specs, dict):
|
|
19
|
+
return False, "Specifications must be a dictionary."
|
|
20
|
+
|
|
21
|
+
brand = specs.get("brand")
|
|
22
|
+
if not brand or brand not in self.supported_brands:
|
|
23
|
+
return False, f"Brand must be one of {self.supported_brands}."
|
|
24
|
+
|
|
25
|
+
product_type = specs.get("type")
|
|
26
|
+
if not product_type:
|
|
27
|
+
return False, "Product type is required."
|
|
28
|
+
|
|
29
|
+
if product_type.lower() == "earbuds":
|
|
30
|
+
driver_size = specs.get("driver_size_mm")
|
|
31
|
+
if driver_size is not None:
|
|
32
|
+
if not (self.min_driver_size_mm <= driver_size <= self.max_driver_size_mm):
|
|
33
|
+
return False, f"Invalid driver size: {driver_size}mm. Must be between {self.min_driver_size_mm} and {self.max_driver_size_mm}mm."
|
|
34
|
+
|
|
35
|
+
playtime = specs.get("playtime_hours")
|
|
36
|
+
if playtime is not None and playtime <= 0:
|
|
37
|
+
return False, "Playtime must be a positive integer/float."
|
|
38
|
+
|
|
39
|
+
elif product_type.lower() == "charger":
|
|
40
|
+
wattage = specs.get("wattage_w")
|
|
41
|
+
if wattage is not None and wattage <= 0:
|
|
42
|
+
return False, "Charger wattage must be positive."
|
|
43
|
+
|
|
44
|
+
return True, "Specifications are valid and conform to product guidelines."
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
class PriceFormatter:
|
|
2
|
+
"""
|
|
3
|
+
Utility to format and normalize prices for e-commerce stores in EGP, USD, or EUR.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
@staticmethod
|
|
7
|
+
def format_egp(amount: float, show_symbol: bool = True) -> str:
|
|
8
|
+
"""
|
|
9
|
+
Formats a number to Egyptian Pound (EGP) format.
|
|
10
|
+
"""
|
|
11
|
+
try:
|
|
12
|
+
val = float(amount)
|
|
13
|
+
formatted = f"{val:,.2f}"
|
|
14
|
+
if show_symbol:
|
|
15
|
+
return f"{formatted} EGP"
|
|
16
|
+
return formatted
|
|
17
|
+
except ValueError:
|
|
18
|
+
return "0.00 EGP"
|
|
19
|
+
|
|
20
|
+
@staticmethod
|
|
21
|
+
def calculate_vat(price: float, vat_rate: float = 0.14) -> float:
|
|
22
|
+
"""
|
|
23
|
+
Calculates VAT (default 14% for Egypt) on the given price.
|
|
24
|
+
"""
|
|
25
|
+
if price <= 0:
|
|
26
|
+
return 0.0
|
|
27
|
+
return round(price * vat_rate, 2)
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cairovolt-price-tracker
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: A lightweight Python utility to parse, format, and validate technical specifications and pricing for electronics accessories.
|
|
5
|
+
Author-email: CairoVolt Developer <dev@cairovolt.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://cairovolt.com/en/
|
|
8
|
+
Project-URL: Documentation, https://github.com/cairovolt/cairovolt-price-tracker
|
|
9
|
+
Project-URL: Store, https://cairovolt.com/en/soundcore/audio/anker-soundcore-r50i
|
|
10
|
+
Project-URL: Repository, https://github.com/cairovolt/cairovolt-price-tracker
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Requires-Python: >=3.8
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
License-File: LICENSE
|
|
17
|
+
Dynamic: license-file
|
|
18
|
+
|
|
19
|
+
# CairoVolt Price Tracker
|
|
20
|
+
|
|
21
|
+
A lightweight Python library to parse, format, and validate technical specifications and pricing structures for electronics and audio accessories.
|
|
22
|
+
|
|
23
|
+
This library was built by [CairoVolt](https://cairovolt.com/en/) to automate stock synchronization and spec validation for online WooCommerce shops. For more details on running a web store, see the [WooCommerce Wikipedia page](https://en.wikipedia.org/wiki/WooCommerce).
|
|
24
|
+
|
|
25
|
+
## Features
|
|
26
|
+
|
|
27
|
+
- **Price Formatting**: Easily format currency in EGP, USD, or EUR.
|
|
28
|
+
- **Specification Validation**: Validate charger wattages, battery capacities, and Bluetooth profiles.
|
|
29
|
+
- **Data Export**: Export structured JSON specifications for platforms like [Anker](https://www.anker.com) and [Soundcore](https://www.soundcore.com) devices.
|
|
30
|
+
|
|
31
|
+
## Installation
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pip install cairovolt-price-tracker
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Usage
|
|
38
|
+
|
|
39
|
+
Here is a quick example of how to validate the specifications of a popular earbuds model like [soundcore r50i](https://cairovolt.com/en/soundcore/audio/anker-soundcore-r50i):
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
from cairovolt_price_tracker.core import SpecValidator
|
|
43
|
+
|
|
44
|
+
# Initialize validator
|
|
45
|
+
validator = SpecValidator()
|
|
46
|
+
|
|
47
|
+
# Define product specs
|
|
48
|
+
product_specs = {
|
|
49
|
+
"brand": "Soundcore",
|
|
50
|
+
"model": "R50i",
|
|
51
|
+
"type": "Earbuds",
|
|
52
|
+
"driver_size_mm": 10,
|
|
53
|
+
"playtime_hours": 30,
|
|
54
|
+
"bluetooth_version": "5.3"
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
# Validate specs
|
|
58
|
+
is_valid, report = validator.validate(product_specs)
|
|
59
|
+
print(f"Is valid: {is_valid}")
|
|
60
|
+
print(report)
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
For guidelines on packaging similar Python projects, check the [Python Packaging User Guide](https://packaging.python.org/en/latest/).
|
|
64
|
+
|
|
65
|
+
## License
|
|
66
|
+
|
|
67
|
+
MIT
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
src/cairovolt_price_tracker/__init__.py
|
|
5
|
+
src/cairovolt_price_tracker/core.py
|
|
6
|
+
src/cairovolt_price_tracker/utils.py
|
|
7
|
+
src/cairovolt_price_tracker.egg-info/PKG-INFO
|
|
8
|
+
src/cairovolt_price_tracker.egg-info/SOURCES.txt
|
|
9
|
+
src/cairovolt_price_tracker.egg-info/dependency_links.txt
|
|
10
|
+
src/cairovolt_price_tracker.egg-info/top_level.txt
|
|
11
|
+
tests/test_core.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
cairovolt_price_tracker
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
from cairovolt_price_tracker.core import SpecValidator
|
|
3
|
+
from cairovolt_price_tracker.utils import PriceFormatter
|
|
4
|
+
|
|
5
|
+
class TestSpecValidator(unittest.TestCase):
|
|
6
|
+
def setUp(self):
|
|
7
|
+
self.validator = SpecValidator()
|
|
8
|
+
|
|
9
|
+
def test_valid_earbuds(self):
|
|
10
|
+
specs = {
|
|
11
|
+
"brand": "Soundcore",
|
|
12
|
+
"model": "R50i",
|
|
13
|
+
"type": "Earbuds",
|
|
14
|
+
"driver_size_mm": 10.0,
|
|
15
|
+
"playtime_hours": 30
|
|
16
|
+
}
|
|
17
|
+
is_valid, msg = self.validator.validate(specs)
|
|
18
|
+
self.assertTrue(is_valid)
|
|
19
|
+
|
|
20
|
+
def test_invalid_brand(self):
|
|
21
|
+
specs = {
|
|
22
|
+
"brand": "UnknownBrand",
|
|
23
|
+
"model": "R50i",
|
|
24
|
+
"type": "Earbuds"
|
|
25
|
+
}
|
|
26
|
+
is_valid, msg = self.validator.validate(specs)
|
|
27
|
+
self.assertFalse(is_valid)
|
|
28
|
+
self.assertIn("Brand must be one of", msg)
|
|
29
|
+
|
|
30
|
+
class TestPriceFormatter(unittest.TestCase):
|
|
31
|
+
def test_format_egp(self):
|
|
32
|
+
self.assertEqual(PriceFormatter.format_egp(1500), "1,500.00 EGP")
|
|
33
|
+
self.assertEqual(PriceFormatter.format_egp(1500.5, False), "1,500.50")
|
|
34
|
+
|
|
35
|
+
def test_calculate_vat(self):
|
|
36
|
+
self.assertEqual(PriceFormatter.calculate_vat(100), 14.0)
|
|
37
|
+
|
|
38
|
+
if __name__ == "__main__":
|
|
39
|
+
unittest.main()
|