Skip to content

Commit

Permalink
Release 3.0
Browse files Browse the repository at this point in the history
  • Loading branch information
kubinka0505 committed Jan 27, 2024
0 parents commit 6ebd7d1
Show file tree
Hide file tree
Showing 12 changed files with 1,336 additions and 0 deletions.
50 changes: 50 additions & 0 deletions .github/workflows/coverage_test_unit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: Test Coverage

on: [push]

jobs:
build:
runs-on: windows-latest

steps:
- name: Checkout repository
uses: actions/checkout@v2

- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: 3.x

- name: Install dependencies
run: |
pip install setuptools pytest-cov
git clone https://github.com/${{ github.repository_owner }}/${{ github.event.repository.name }}
cd ${{ github.event.repository.name }}/Files
python setup.py install
- name: Run tests and generate coverage report
run: |
cd Files/tests
coverage run -m unittest unit.py
coverage report
coverage xml -o coverage.xml
- name: Upload artifacts
uses: actions/upload-artifact@v2
with:
name: unit-test
path: Files/tests/coverage.xml

send:
runs-on: ubuntu-latest
needs: build

steps:
- name: Retrieve coverage
uses: actions/download-artifact@v2

- name: Coverage reporter
uses: codacy/codacy-coverage-reporter-action@v1.3.0
with:
project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
coverage-reports: unit-test/coverage.xml
67 changes: 67 additions & 0 deletions Documents/ChangeLog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
## 3.0
### Added ➕
- Editable properties.
### Modified 🔁
- Program files structure.
- Improved documentation.
- Path system.
### Fixed 📝
- Issue leading to NT directories not having creation time set.

## 2.0
### Added ➕
- `Batch` alias for `filedate.Utils.Keep`
- Support for setting dates to directories.
- Support for copying dates to directories.
### Modified 🔁
- Program files structure.
- `filedate.File` file path system.
### Fixed 📝
- Bugs.
### Removed 🚫
- `filedate.Utils.Swap`
- `fromfn` alias from `filedate.Utils.fromname`
- `filedate.Utils.fromfile` to `filedate.Utils.Name`

## 1.8
### Added ➕
- `filedate.Utils.fromfile`

## 1.7
### Fixed 📝
- Bugs.

## 1.6
### Added ➕
- `filedate.Utils.Swap`
### Fixed 📝
- Bugs.

## 1.5
### Fixed 📝
- Bugs.

## 1.4
### Added ➕
- `filedate.Utils.copy`
### Fixed 📝
- Bugs.

## 1.3
### Modified 🔁
- Renamed:
- `filedate.FileDate` to `filedate.File`
- `filedate.Utils.release` to `filedate.Utils.drop`
- Reduced code size.

## 1.2
### Fixed 📝
- Code refraction.
- Bugs.

## 1.1
### Modified 🔁
- Code structure.

## 1.0
- Initial release.
1 change: 1 addition & 0 deletions Documents/Pictures/filedate.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions Files/!_Install.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
@echo off
color 0e

for %%I in (..) do set Name=%%~nxI

pip uninstall %Name% -y
py setup.py install

rd build dist %Name%.egg-info /S /Q
66 changes: 66 additions & 0 deletions Files/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import os
from shutil import rmtree
from setuptools import setup, find_packages

# Remove directories after installing
cleanup = True

#-=-=-=-#

__title__ = os.path.basename(os.path.dirname(os.path.dirname(__file__)))

#-=-=-=-#

# Cleanup
if cleanup:
if "install" in os.sys.argv:

# Built directories
dirs = [
"build", "dist", "name",
f"{__title__}.egg-info"
]

for directory in dirs:
rmtree(directory, True)

directory = "src"
if os.path.exists(directory):
os.rename(directory, __title__)

#-=-=-=-#

desc = open("../ReadMe.md", encoding = "UTF-8").read().rstrip()
tags = [__title__, "file", "date", "change", "changing", "changer"]

setup(
name = __title__,
description = desc,
long_description = desc,
version = "3.0",
author = "kubinka0505",
url = f"https://github.com/kubinka0505/{__title__}",
keywords = tags,
classifiers = [
"Development Status :: 6 - Mature",
"Environment :: Console",
"Intended Audience :: Developers",
"Intended Audience :: End Users/Desktop",
"Intended Audience :: System Administrators",
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
"Natural Language :: English",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3 :: Only",
"Topic :: Desktop Environment :: File Managers",
],
python_requires = ">=3.4",
install_requires = [
"python-dateutil",
],
packages = find_packages()
)

#-=-=-=-#

if os.path.exists(__title__):
os.rename(__title__, directory)
19 changes: 19 additions & 0 deletions Files/src/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
"""Simple, convenient and cross-platform file date changing library."""

__author__ = "kubinka0505"
__credits__ = __author__
__version__ = "3.0"
__date__ = "28th December 2023"

#-=-=-=-#

from .config import *
from .core import *
from .utils import *

#-=-=-=-#

if is_NT:
del byref, windll

del is_NT
15 changes: 15 additions & 0 deletions Files/src/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
"""Module configuration classes and variables."""

class exceptions:

class path:
NOT_FOUND = FileNotFoundError("File was not found")
NO_DATE = ValueError("Parsed string does not contain a date")

#-=-=-=-=-=-#

# Setup

import os

is_NT = os.sys.platform.lower().startswith("win")
151 changes: 151 additions & 0 deletions Files/src/core.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
"""File date manager core."""

from .config import exceptions, is_NT

import os
from pathlib import Path
from datetime import datetime
from dateutil.parser import parse

if is_NT:
from ctypes import windll, wintypes, byref

#-=-=-=-#

class File:
def __init__(self, path: str):
"""
Initialize self. See help(type(self)) for accurate signature.
Args:
path: Existing file path.
"""
path = os.path.abspath(path)
path = str(Path(path).resolve())

if not os.path.exists(path):
raise exceptions.path.NOT_FOUND

self.path = path

def _modify(self, parameter: str):
if isinstance(parameter, str):
parameter = parse(parameter).timestamp()
try:
parameter = parameter // 1
except TypeError:
parameter = parameter.timestamp()

return parameter

#-=-=-=-#
# Properties

@property
def file(self):
return self.path

## Created

@property
def created(self):
return self.get()["created"]

@created.setter
def created(self, date) -> datetime:
return self.set(created = date)

#if not is_NT:
# del created

## Modified

@property
def modified(self):
return self.get()["modified"]

@modified.setter
def modified(self, date) -> datetime:
return self.set(modified = date)

## Accessed

@property
def accessed(self):
return self.get()["accessed"]

@accessed.setter
def accessed(self, date) -> datetime:
return self.set(accessed = date)

#-=-=-=-#

def get(self) -> dict:
"""
Returns:
dict: `datetime` objects - when file was created, modified and accessed.
"""
info = os.stat(self.path)
dates = {
"created": info.st_ctime,
"modified": info.st_mtime,
"accessed": info.st_atime
}

for key, value in dates.items():
dates[key] = datetime.fromtimestamp(value).replace(microsecond = 0)

return dates

def set(self, modified: str = None, created: str = None, accessed: str = None):
"""
Modifies file's dates.
Arguments can be string date representation parsable by `dateutil.parser.parse` or time from epoch.
Args:
created: Date of file creation. Windows only - sets `modified` time on other systems.
modified: Date of file last modification.
accessed: Date of file last access.
"""
dates = File(self.path).get()

created = int((self._modify(created) if created else dates["created"].timestamp()))
modified = int((self._modify(modified) if modified else dates["modified"].timestamp()))
accessed = int((self._modify(accessed) if accessed else dates["accessed"].timestamp()))

err = 0
try:
if created:
if is_NT:
timestamp = int((created * 1E7) + 116444736E9)
ctime = wintypes.FILETIME(timestamp & 0xFFFFFFFF, timestamp >> 32)
handle = windll.kernel32.CreateFileW(self.path, 256, 0, None, 3, 33554560, None)

windll.kernel32.SetFileTime(handle, byref(ctime), None, None)
windll.kernel32.CloseHandle(handle)

os.utime(self.path, (accessed, modified))
except OSError:
err = exceptions.date.WRONG

if err:
raise err

#-=-=-=-=-=-#

# Special methods

def __dir__(self):
return self.get().values()

#-=-=-=-=-=-#

# Aliases

get_dates = get
date_created = created
date_modified = modified
date_accessed = accessed

file = File
Loading

0 comments on commit 6ebd7d1

Please sign in to comment.