Skip to content

Commit

Permalink
feat: add DataObject, DataAdapters and DataPrinters classes
Browse files Browse the repository at this point in the history
  • Loading branch information
MatteoGuadrini committed Apr 19, 2024
2 parents 4c49378 + 856c41b commit 5b1606a
Show file tree
Hide file tree
Showing 19 changed files with 907 additions and 361 deletions.
3 changes: 1 addition & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ jobs:
- checkout
- run: sudo apt update && sudo apt install -y freetds-dev libssl-dev python-dev freetds-bin
- run: sudo pip install --upgrade pip
- run: sudo pip install cython
- run: sudo pip install pymssql
- run: sudo pip install "Cython<3"
- run: sudo pip install numpy
- run: sudo pip install pandas
- run: sudo python setup.py install
Expand Down
35 changes: 35 additions & 0 deletions .readthedocs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Read the Docs configuration file for Sphinx projects
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details

# Required
version: 2

# Set the OS, Python version and other tools you might need
build:
os: ubuntu-22.04
tools:
python: "3.11"
# You can also specify other tool versions:
# nodejs: "20"
# rust: "1.70"
# golang: "1.20"

# Build documentation in the "docs/" directory with Sphinx
sphinx:
configuration: docs/source/conf.py
# You can configure Sphinx to use a different builder, for instance use the dirhtml builder for simpler URLs
# builder: "dirhtml"
# Fail on all warnings to avoid broken references
# fail_on_warning: true

# Optionally build your docs in additional formats such as PDF and ePub
# formats:
# - pdf
# - epub

# Optional but recommended, declare the Python requirements required
# to build your documentation
# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
python:
install:
- requirements: docs/requirements.txt
23 changes: 23 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,28 @@
# Release notes

## 1.7.0
Apr 19, 2024

- Remove **pymssql** support
- Add **DataObject** class
- Add **DataAdapters** class
- Add **DataPrinters** class
- Add **aggregate** into _DataAdapters_ class
- Add **merge** method into _DataAdapters_ class
- Add **counter** method into _DataAdapters_ class
- Add **chunks** method into _DataAdapters_ class
- Add **deduplicate** method into _DataAdapters_ class
- Add **iter** method into _DataAdapters_ class
- Add **getitem** method into _DataAdapters_ class
- Add **getitem** method into _DataAdapters_ class
- Add **repr** and **str** function into _DataPrinters_ class
- Add **average** method into _DataPrinters_ class
- Add **most_common** method into _DataPrinters_ class
- Add **percentage** method into _DataPrinters_ class
- Add **len** method into _DataPrinters_ class
- Add **DataAdapters** and **DataPrinters** classes into _Report_ class
- Add **DataObjectError** exception class

## 1.6.0
Jul 14, 2023

Expand Down
1 change: 0 additions & 1 deletion docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
ldap3
pymssql
mysql-connector-python
psycopg2-binary
tablib
Expand Down
23 changes: 10 additions & 13 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,28 +15,27 @@
# sys.path.insert(0, os.path.abspath('.'))
import os
import sys
sys.path.insert(0, os.path.abspath('../..'))

import __info__
sys.path.insert(0, os.path.abspath("../.."))

# -- Project information -----------------------------------------------------

project = 'pyreports'
copyright = '2021, Matteo Guadrini'
author = __info__.__author__
project = "pyreports"
copyright = "2024, Matteo Guadrini"
author = "Matteo Guadrini"

# The full version, including alpha/beta/rc tags
release = __info__.__version__
release = "1.7.0"

# -- General configuration ---------------------------------------------------

# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest']
extensions = ["sphinx.ext.autodoc", "sphinx.ext.doctest"]

# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
templates_path = ["_templates"]

# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
Expand All @@ -53,11 +52,9 @@
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
html_static_path = ["_static"]

html_theme_options = {
'logo_only': False
}
html_theme_options = {"logo_only": False}
html_logo = "_static/pyreports.svg"

master_doc = 'index'
master_doc = "index"
119 changes: 118 additions & 1 deletion docs/source/datatools.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,107 @@ In this section we will see all these functions contained in the **datatools** m
.. toctree::


DataObject
----------

**DataObject** class represents a pure *Dataset*.

.. autoclass:: pyreports.DataObject
:members:

.. code-block:: python
import pyreports, tablib
data = pyreports.DataObject(tablib.Dataset(*[("Arthur", "Dent", 42)]))
assert isinstance(data.data, tablib.Dataset) == True
DataAdapters
------------

**DataAdapters** class is an object that contains methods that modifying *Dataset*.

.. code-block:: python
import pyreports, tablib
data = pyreports.DataAdapters(tablib.Dataset(*[("Arthur", "Dent", 42)]))
assert isinstance(data.data, tablib.Dataset) == True
# Aggregate
planets = tablib.Dataset(*[("Heart",)])
data.aggregate(planets)
# Merge
others = tablib.Dataset(*[("Betelgeuse", "Ford", "Prefect", 42)])
data.merge(others)
# Counter
data = pyreports.DataAdapters(Dataset(*[("Heart", "Arthur", "Dent", 42)]))
data.merge(self.data)
counter = data.counter()
assert counter["Arthur"] == 2
# Chunks
data.data.headers = ["planet", "name", "surname", "age"]
assert list(data.chunks(4))[0][0] == ("Heart", "Arthur", "Dent", 42)
# Deduplicate
data.deduplicate()
assert len(data.data) == 2
# Get items
assert data[1] == ("Betelgeuse", "Ford", "Prefect", 42)
# Iter items
for item in data:
print(item)
.. autoclass:: pyreports.DataAdapters
:members:

DataPrinters
------------

**DataPrinters** class is an object that contains methods that printing *Dataset*'s information.

.. code-block:: python
import pyreports, tablib
data = pyreports.DataPrinters(tablib.Dataset(*[("Arthur", "Dent", 42), ("Ford", "Prefect", 42)], headers=["name", "surname", "age"]))
assert isinstance(data.data, tablib.Dataset) == True
# Print
data.print()
# Average
assert data.average(2) == 42
assert data.average("age") == 42
# Most common
data.data.append(("Ford", "Prefect", 42))
assert data.most_common(0) == "Ford"
assert data.most_common("name") == "Ford"
# Percentage
assert data.percentage("Ford") == 66.66666666666666
# Representation
assert repr(data) == "<DataObject, headers=['name', 'surname', 'age'], rows=3>"
# String
assert str(data) == 'name |surname|age\n------|-------|---\nArthur|Dent |42 \nFord |Prefect|42 \nFord |Prefect|42 '
# Length
assert len(data) == 3
.. autoclass:: pyreports.DataPrinters
:members:


Average
Expand Down Expand Up @@ -137,4 +238,20 @@ The **chunks** function divides a *Dataset* into pieces from *N* (``int``). This
print(list(new_data)) # [[('Arthur', 'Dent', 55000), ('Ford', 'Prefect', 65000)], [('Tricia', 'McMillian', 55000), ('Zaphod', 'Beeblebrox', 65000)]]
.. note::
If the division does not result zero, the last tuple of elements will be a smaller number.
If the division does not result zero, the last tuple of elements will be a smaller number.

Deduplicate
-----------

The **deduplicate** function remove duplicated rows into *Dataset* objects.

.. code-block:: python
import pyreports
# Build a datasets
employee1 = tablib.Dataset([('Arthur', 'Dent', 55000), ('Ford', 'Prefect', 65000), ('Ford', 'Prefect', 65000)], headers=['name', 'surname', 'salary'])
# Remove duplicated rows (removed the last ('Ford', 'Prefect', 65000))
pyreports.deduplicate(employee1)
print(len(employee1)) # 2
2 changes: 1 addition & 1 deletion docs/source/example.rst
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ In this example, we will take two different inputs, and combine them to export a
# Config Unix application file: this is a FileManager object
config_file = pyreports.manager('yaml', '/home/myapp.yml')
# Console admin: this is a DatabaseManager object
mydb = pyreports.manager('mssql', server='mssql1.local', database='admins', user='sa', password='sa0000')
mydb = pyreports.manager('mysql', server='mysql1.local', database='admins', user='sa', password='sa0000')
# Get data
admin_app = config_file.read() # return Dataset object: three column (name, shell, login)
mydb.execute('SELECT * FROM console_admins')
Expand Down
2 changes: 0 additions & 2 deletions docs/source/managers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ Each type of manager is managed by micro types; Below is the complete list:

#. Database
#. sqlite (SQLite)
#. mssql (Microsoft SQL)
#. mysql (MySQL or MariaDB)
#. postgresql (PostgreSQL or EnterpriseDB)
#. File
Expand All @@ -41,7 +40,6 @@ Each type of manager is managed by micro types; Below is the complete list:
# DatabaseManager object
sqlite_db = pyreports.manager('sqlite', database='/tmp/mydb.db')
mssql_db = pyreports.manager('mssql', server='mssql1.local', database='test', user='dba', password='dba0000')
mysql_db = pyreports.manager('mysql', host='mysql1.local', database='test', user='dba', password='dba0000')
postgresql_db = pyreports.manager('postgresql', host='postgresql1.local', database='test', user='dba', password='dba0000')
Expand Down
36 changes: 18 additions & 18 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -245,24 +245,24 @@ <h3 class="sub-title text-center">Shell CLI</h3>
<pre><code class="language-shell">
$ cat car.yml
reports:
- report:
title: 'Red ford machine'
input:
manager: 'mysql'
source:
# Connection parameters of my mysql database
host: 'mysql1.local'
database: 'cars'
user: 'admin'
password: 'dba0000'
params:
query: 'SELECT * FROM cars WHERE brand = %s AND color = %s'
params: ['ford', 'red']
# Filter km
filters: [40000, 45000]
output:
manager: 'csv'
filename: '/tmp/car_csv.csv'
- report:
title: 'Red ford machine'
input:
manager: 'mysql'
source:
# Connection parameters of my mysql database
host: 'mysql1.local'
database: 'cars'
user: 'admin'
password: 'dba0000'
params:
query: 'SELECT * FROM cars WHERE brand = %s AND color = %s'
params: ['ford', 'red']
# Filter km
filters: [40000, 45000]
output:
manager: 'csv'
filename: '/tmp/car_csv.csv'

$ report car.yaml
</code></pre>
Expand Down
14 changes: 7 additions & 7 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ build-backend = "setuptools.build_meta"

[project]
name = "pyreports"
version = "1.6.0"
version = "1.7.0"
readme = "README.md"
license = {text = "GNU General Public License v3.0"}
license = { text = "GNU General Public License v3.0" }
keywords = ['pyreports', 'reports', 'report', 'csv', 'yaml', 'export',
'excel', 'database', 'ldap', 'dataset', 'file', 'executor', 'book']
'excel', 'database', 'ldap', 'dataset', 'file', 'executor', 'book']
authors = [{ name = "Matteo Guadrini", email = "matteo.guadrini@hotmail.it" }]
maintainers = [
{ name = "Matteo Guadrini", email = "matteo.guadrini@hotmail.it" },
Expand All @@ -20,14 +20,14 @@ classifiers = [
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
"Operating System :: OS Independent",
]
dependencies = ['ldap3', 'pymssql', 'mysql-connector-python',
'psycopg2-binary', 'tablib', 'tablib[all]', 'nosqlapi', 'pyyaml']
dependencies = ['ldap3', 'mysql-connector-python',
'psycopg2-binary', 'tablib', 'tablib[all]', 'nosqlapi', 'pyyaml']

[project.scripts]
reports = "pyreports.cli:main"

[project.urls]
homepage = "https://github.com/MatteoGuadrini/pyreports'"
documentation = "https://pyreports.readthedocs.io/en/latest/"
repository = "https://github.com/MatteoGuadrini/pyreports/pyreports.git"
changelog = "https://github.com/MatteoGuadrini/pyreports/blob/master/CHANGES.md"
repository = "https://github.com/MatteoGuadrini/pyreports.git"
changelog = "https://github.com/MatteoGuadrini/pyreports/blob/master/CHANGES.md"
Loading

0 comments on commit 5b1606a

Please sign in to comment.