Skip to content

Commit

Permalink
Python 3.12 support (ThePornDatabase#225)
Browse files Browse the repository at this point in the history
* add python 3.12 support and drop 3.8 support

* minor ui fixes

* format files

* get rid of imagehash

* replace flakeheaven with ruff
  • Loading branch information
DirtyRacer1337 authored Nov 7, 2023
1 parent 6c423eb commit db68820
Show file tree
Hide file tree
Showing 43 changed files with 1,240 additions and 1,317 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
python-version: [ '3.8', '3.9', '3.10', '3.11' ]
python-version: [ '3.9', '3.10', '3.11', '3.12' ]
steps:
- name: Checkout
uses: actions/checkout@v3
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ namer/web/public/assets
namer/web/templates
namer/tools
.flakeheaven_cache
.ruff_cache
2 changes: 1 addition & 1 deletion lint-staged.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module.exports = {
'*.py': (filenames) => filenames.map((filename) => `poetry run flakeheaven lint --format default "${filename}"`),
'*.py': (filenames) => filenames.map((filename) => `poetry run ruff check --output-format text "${filename}"`),
'*.js': (filenames) => filenames.map((filename) => `pnpm eslint --no-color "${filename}"`)
}
21 changes: 11 additions & 10 deletions namer/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@
from namer.models import db

DESCRIPTION = (
namer.namer.DESCRIPTION + """
namer.namer.DESCRIPTION
+ """
The first argument should be 'watchdog', 'rename', 'suggest', or 'help' to see this message, for more help on rename, call
namer 'namer rename -h'
Expand All @@ -42,9 +43,9 @@ def create_default_config_if_missing():
"""
Find or create config.
"""
config_file = Path(".namer.conf")
print("Creating default config file here: {}", config_file)
print("please edit the token or any other settings whose defaults you want changed.")
config_file = Path('.namer.conf')
print('Creating default config file here: {}', config_file)
print('please edit the token or any other settings whose defaults you want changed.')


def main():
Expand All @@ -68,20 +69,20 @@ def main():
db.generate_mapping(create_tables=True)

arg1 = None if len(arg_list) == 0 else arg_list[0]
if arg1 == "watchdog":
if arg1 == 'watchdog':
level = 'DEBUG' if config.debug else 'INFO'
logger.add(sys.stdout, format="<green>{time:YYYY-MM-DD HH:mm:ss}</green> | <level>{level.icon} {level: <8}</level> | {message}", level=level, diagnose=config.diagnose_errors)
logger.add(sys.stdout, format='<green>{time:YYYY-MM-DD HH:mm:ss}</green> | <level>{level.icon} {level: <8}</level> | {message}', level=level, diagnose=config.diagnose_errors)
namer.watchdog.create_watcher(config).run()
elif arg1 == "rename":
elif arg1 == 'rename':
namer.namer.main(arg_list[1:])
elif arg1 == "suggest":
elif arg1 == 'suggest':
namer.metadataapi.main(arg_list[1:])
elif arg1 in ["-h", "help", None]:
elif arg1 in ['-h', 'help', None]:
print(DESCRIPTION)

if config.use_requests_cache and config.cache_session:
config.cache_session.cache.delete(expired=True)


if __name__ == "__main__":
if __name__ == '__main__':
main()
38 changes: 19 additions & 19 deletions namer/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,13 @@ def move_command_files(target: Optional[Command], new_target: Path, is_auto: boo

if target.target_directory and target.input_file == target.target_directory:
working_dir = Path(new_target) / target.target_directory.name
logger.info("Moving {} to {} for processing", target.target_directory, working_dir)
logger.info('Moving {} to {} for processing', target.target_directory, working_dir)
shutil.move(target.target_directory, working_dir)
output = make_command(working_dir, target.config, is_auto=is_auto)
else:
working_file = Path(new_target) / target.target_movie_file.name
shutil.move(target.target_movie_file, working_file)
logger.info("Moving {} to {} for processing", target.target_movie_file, working_file)
logger.info('Moving {} to {} for processing', target.target_movie_file, working_file)
output = make_command(working_file, target.config, is_auto=is_auto)

if output:
Expand All @@ -105,9 +105,9 @@ def write_log_file(movie_file: Optional[Path], match_attempts: Optional[Comparis
"""
log_name = None
if movie_file:
log_name = movie_file.with_name(movie_file.stem + "_namer.json.gz")
logger.info("Writing log to {}", log_name)
with open(log_name, "wb") as log_file:
log_name = movie_file.with_name(movie_file.stem + '_namer.json.gz')
logger.info('Writing log to {}', log_name)
with open(log_name, 'wb') as log_file:
if match_attempts:
for result in match_attempts.results:
del result.looked_up.original_query
Expand All @@ -125,8 +125,8 @@ def write_log_file(movie_file: Optional[Path], match_attempts: Optional[Comparis


def _set_perms(target: Path, config: NamerConfig):
file_perm: Optional[int] = (int(str(config.set_file_permissions), 8) if config.set_file_permissions else None)
dir_perm: Optional[int] = (int(str(config.set_dir_permissions), 8) if config.set_dir_permissions else None)
file_perm: Optional[int] = int(str(config.set_file_permissions), 8) if config.set_file_permissions else None
dir_perm: Optional[int] = int(str(config.set_dir_permissions), 8) if config.set_dir_permissions else None

if config.set_gid:
os.lchown(target, uid=-1, gid=config.set_gid)
Expand All @@ -145,10 +145,10 @@ def set_permissions(file: Optional[Path], config: NamerConfig):
Given a file or dir, set permissions from NamerConfig.set_file_permissions,
NamerConfig.set_dir_permissions, and uid/gid if set for the current process recursively.
"""
if system() != "Windows" and file and file.exists() and config.update_permissions_ownership:
if system() != 'Windows' and file and file.exists() and config.update_permissions_ownership:
_set_perms(file, config)
if file.is_dir():
for target in file.rglob("**/*"):
for target in file.rglob('**/*'):
_set_perms(target, config)


Expand Down Expand Up @@ -225,7 +225,7 @@ def move_to_final_location(command: Command, new_metadata: LookedUpFileInfo) ->
# Find non-conflicting movie name.
movies: List[str] = []
while True:
relative_path = Path(new_metadata.new_file_name(name_template, command.config, f"({infix})"))
relative_path = Path(new_metadata.new_file_name(name_template, command.config, f'({infix})'))
movie_name = target_dir / relative_path
movie_name = movie_name.resolve()
infix += 1
Expand All @@ -245,7 +245,7 @@ def move_to_final_location(command: Command, new_metadata: LookedUpFileInfo) ->
if not command.config.preserve_duplicates and movies:
# Now set to the final name location since -- will grab the metadata requested
# incase it has been updated.
relative_path = Path(new_metadata.new_file_name(name_template, command.config, "(0)"))
relative_path = Path(new_metadata.new_file_name(name_template, command.config, '(0)'))

# no move best match to primary movie location.
final_location = (target_dir / relative_path).resolve()
Expand All @@ -268,9 +268,9 @@ def move_to_final_location(command: Command, new_metadata: LookedUpFileInfo) ->
# we want to retain files if asked and if a directory will exist.
if command.target_directory and not command.config.del_other_files and containing_dir:
containing_dir.mkdir(parents=True, exist_ok=True)
logger.info(f"moving other files to new dir: {containing_dir} from {command.target_directory}")
logger.info(f'moving other files to new dir: {containing_dir} from {command.target_directory}')
# first remove namer log if exists
possible_log = command.target_movie_file.parent / (command.target_movie_file.stem + "_namer.json.gz")
possible_log = command.target_movie_file.parent / (command.target_movie_file.stem + '_namer.json.gz')
if possible_log.exists():
possible_log.unlink()

Expand Down Expand Up @@ -327,7 +327,7 @@ def gather_target_files_from_dir(dir_to_scan: Path, config: NamerConfig) -> Iter
Find files to process in a target directory.
"""
if dir_to_scan and dir_to_scan.is_dir() and dir_to_scan.exists():
logger.info("Scanning dir {} for sub-dirs/files to process", dir_to_scan)
logger.info('Scanning dir {} for sub-dirs/files to process', dir_to_scan)
mapped: Iterable = map(lambda file: make_command((dir_to_scan / file), config), dir_to_scan.iterdir())
filtered: Iterable[Command] = filter(lambda file: file is not None, mapped) # type: ignore
return filtered
Expand Down Expand Up @@ -362,7 +362,7 @@ def find_target_file(root_dir: Path, config: NamerConfig) -> Optional[Path]:
"""
returns largest matching file
"""
list_of_files = list(root_dir.rglob("**/*.*"))
list_of_files = list(root_dir.rglob('**/*.*'))
file = None
if list_of_files:
for target_ext in config.target_extensions:
Expand Down Expand Up @@ -410,10 +410,10 @@ def main(arg_list: List[str]):
"""
Attempt to parse a name.
"""
description = "You are using the file name parser of the Namer project. Expects a single input, and will output the contents of FileInfo, which is the internal input to the namer_metadatapi.py script. Output will be the representation of that FileInfo.\n"
description = 'You are using the file name parser of the Namer project. Expects a single input, and will output the contents of FileInfo, which is the internal input to the namer_metadatapi.py script. Output will be the representation of that FileInfo.\n'
parser = argparse.ArgumentParser(description=description)
parser.add_argument("-f", "--file", help="String to parse for name parts", required=True)
parser.add_argument("-c", "--configfile", help="override location for a configuration file.", type=Path)
parser.add_argument('-f', '--file', help='String to parse for name parts', required=True)
parser.add_argument('-c', '--configfile', help='override location for a configuration file.', type=Path)
args = parser.parse_args(arg_list)
target = Path(args.file).absolute()
config_file = Path(args.configfile).absolute()
Expand All @@ -422,5 +422,5 @@ def main(arg_list: List[str]):
print(target_file.parsed_file)


if __name__ == "__main__":
if __name__ == '__main__':
main(arg_list=sys.argv[1:])
62 changes: 31 additions & 31 deletions namer/comparison_results.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,14 @@ def __init__(self, name, role=None, image=None):
self.image = image

def __str__(self):
name = "Unknown" if self.name is None else self.name
name = 'Unknown' if self.name is None else self.name
if self.role:
return name + " (" + self.role + ")"
return name + ' (' + self.role + ')'

return name

def __repr__(self):
return f"Performer[name={self.name}, role={self.role}, image={self.image}]"
return f'Performer[name={self.name}, role={self.role}, image={self.image}]'


class SceneType(str, Enum):
Expand Down Expand Up @@ -196,54 +196,54 @@ def as_dict(self, config: NamerConfig):
res = self.resolution
res_str: Optional[str] = None
if res:
res_str = "2160p" if res == 2160 else f"{res}p" if res in [1080, 720, 480] else f"{res}"
res_str = '2160p' if res == 2160 else f'{res}p' if res in [1080, 720, 480] else f'{res}'

vr = ""
vr = ''
if (self.site and self.site.lower() in config.vr_studios) or any(tag.strip().lower() in config.vr_tags for tag in self.tags):
vr = "vr"
vr = 'vr'

if self.original_query and '/movies' in self.original_query and (self.site and self.site.lower().replace(" ", "") not in config.movie_data_preferred):
if self.original_query and '/movies' in self.original_query and (self.site and self.site.lower().replace(' ', '') not in config.movie_data_preferred):
self.type = SceneType.MOVIE
elif self.original_query and '/jav' in self.original_query:
self.type = SceneType.JAV
else:
self.type = SceneType.SCENE

return {
"uuid": self.uuid,
"date": self.date,
"year": self.date[0:4] if self.date else None,
"description": self.description,
"name": self.name,
"site": self.site.replace(" ", "") if self.site else None,
"full_site": self.site,
"parent": self.parent.replace(" ", "") if self.parent else None,
"full_parent": self.parent,
"network": self.network.replace(" ", "") if self.network else None,
"full_network": self.network,
"performers": ", ".join(map(lambda p: p.name, filter(lambda p: p.role == "Female", self.performers))) if self.performers else None,
"all_performers": ", ".join(map(lambda p: p.name, self.performers)) if self.performers else None,
"ext": self.original_parsed_filename.extension if self.original_parsed_filename else None,
"trans": self.original_parsed_filename.trans if self.original_parsed_filename else None,
"vr": vr,
"resolution": res_str,
"type": self.type.value,
"external_id": self.external_id,
'uuid': self.uuid,
'date': self.date,
'year': self.date[0:4] if self.date else None,
'description': self.description,
'name': self.name,
'site': self.site.replace(' ', '') if self.site else None,
'full_site': self.site,
'parent': self.parent.replace(' ', '') if self.parent else None,
'full_parent': self.parent,
'network': self.network.replace(' ', '') if self.network else None,
'full_network': self.network,
'performers': ', '.join(map(lambda p: p.name, filter(lambda p: p.role == 'Female', self.performers))) if self.performers else None,
'all_performers': ', '.join(map(lambda p: p.name, self.performers)) if self.performers else None,
'ext': self.original_parsed_filename.extension if self.original_parsed_filename else None,
'trans': self.original_parsed_filename.trans if self.original_parsed_filename else None,
'vr': vr,
'resolution': res_str,
'type': self.type.value,
'external_id': self.external_id,
}

def new_file_name(self, template: str, config: NamerConfig, infix: str = "(0)") -> str:
def new_file_name(self, template: str, config: NamerConfig, infix: str = '(0)') -> str:
"""
Constructs a new file name based on a template (describe in NamerConfig)
"""
dictionary = self.as_dict(config)
clean_dic = self.__cleanup_dictionary(dictionary)
fmt = PartialFormatter(missing="", bad_fmt="---")
fmt = PartialFormatter(missing='', bad_fmt='---')

name = fmt.format(template, **clean_dic)
if name.startswith("/"):
name = "." + name
if name.startswith('/'):
name = '.' + name

if infix != "(0)":
if infix != '(0)':
# will apply the infix before the file extension if just a file name, if a path, with apply
# the infix after the fist part (first directory name) of the (sub)path
path = PurePath(name)
Expand Down
Loading

0 comments on commit db68820

Please sign in to comment.