Преглед на файлове

Start working on project basics.

Cixo Develop преди 3 месеца
родител
ревизия
7c6127f02b

+ 8 - 0
source/cx_pynstaller/__init__.py

@@ -0,0 +1,8 @@
+from .encode import encode
+from .decode import decode
+
+from .command import command
+from .command import encoded_command
+
+from .file import file
+from .file import encoded_file

+ 24 - 0
source/cx_pynstaller/command.py

@@ -0,0 +1,24 @@
+from .encode import encode
+from .decode import decode
+
+class command(encode):
+    def __init__(self, content: str) -> None:
+        self.__content = content
+
+    @property
+    def content(self) -> str:
+        return self.__content
+
+    def encode(self) -> object:
+        return encoded_command(self._encode_str(self.content))
+
+class encoded_command(decode):
+    def __init__(self, content: str) -> None:
+        self.__content = content
+
+    @property
+    def encoded_content(self) -> str:
+        return self.__content
+
+    def decode(self) -> command:
+        return command(self._decode_str(self.encoded_content))

+ 11 - 0
source/cx_pynstaller/decode.py

@@ -0,0 +1,11 @@
+from .exceptions import abstract
+
+class decode:
+    def _decode_bytes(self, content: str) -> bytes: 
+        return bytes.fromhex(content)
+
+    def _decode_str(self, content: str) -> str: 
+        return bytes.fromhex(content).decode("utf-8")
+
+    def decode(self) -> object | str | bytes:
+        raise abstract()

+ 11 - 0
source/cx_pynstaller/encode.py

@@ -0,0 +1,11 @@
+from .exceptions import abstract
+
+class encode:
+    def _encode_bytes(self, content: bytes) -> str:
+        return content.hex()
+
+    def _encode_str(self, content: str) -> str:
+        return content.encode("utf-8").hex()
+
+    def encode(self) -> object | str: 
+        raise abstract()

+ 29 - 0
source/cx_pynstaller/exceptions.py

@@ -0,0 +1,29 @@
+import pathlib
+
+from .file import file
+from .command import command
+
+class abstract(TypeError):
+    def __init__(self) -> None:
+        super().__init__("This is abstract function.")
+
+class not_exists(RuntimeError):
+    def __init__(self, target: pathlib.Path) -> None:
+        super().__init__("File \"" + str(target) + "\" not exists.")
+
+class already_packed(RuntimeError):
+    def __init__(self, target: file) -> None:
+        super().__init__(
+            "File for \"" + target.path_name + "\" already packed."
+        )
+
+class broken_package(RuntimeError):
+    def __init__(self, error: Exception) -> None:
+        super().__init__("Can not unpack broken package.\n" + str(error))
+
+class not_readable(Exception):
+    def __init__(self, target: pathlib.Path, error: Exception) -> None:
+        super().__init__(
+            "File \"" + str(target) + "\" can not being read. " \
+            + "Because of \"" + str(error) + "\" exception."
+        )

+ 47 - 0
source/cx_pynstaller/file.py

@@ -0,0 +1,47 @@
+import pathlib
+
+from .encode import encode
+from .decode import decode
+
+class file(encode):
+    def __init__(self, path: pathlib.Path, content: bytes) -> None:
+        self.__path = path
+        self.__content = content
+
+    @property
+    def path(self) -> pathlib.Path:
+        return self.__path
+
+    @property
+    def content(self) -> bytes: 
+        return self.__content
+
+    @property
+    def path_name(self) -> str:
+        return str(self.__path)
+
+    def encode(self) -> object:
+        encoded_path = self._encode_str(self.path_name)
+        encoded_content = self._encode_bytes(self.content)
+
+        return encoded_file(encoded_path, encoded_content)
+
+class encoded_file(decode):
+    def __init__(self, path: str, content: str) -> None:
+        self.__path = path
+        self.__content = content
+
+    @property
+    def encoded_path(self) -> str:
+        return self.__path
+
+    @property
+    def encoded_content(self) -> str:
+        return self.__content
+
+    def decode(self) -> file:
+        content = self._decode_bytes(self.encoded_content)
+        path_name = self._decode_str(self.encoded_path)
+        path = pathlib.Path(path_name)
+
+        return file(path, content)

+ 10 - 0
source/cx_pynstaller/file_blob.py

@@ -0,0 +1,10 @@
+import pathlib
+
+from .file import file
+
+class file_blob:
+    def __init__(self, content: bytes) -> None:
+        self.__content = content
+
+    def locate(self, where: pathlib.Path) -> file:
+        return file(where, self.__content)

+ 21 - 0
source/cx_pynstaller/file_laoder.py

@@ -0,0 +1,21 @@
+import pathlib
+
+from .file_blob import file_blob
+from .exceptions import not_exists
+from .exceptions import not_readable
+
+class file_loader:
+    def __init__(self, source: pathlib.Path) -> None:
+        if not source.is_file():
+            raise not_exists(source)
+
+        self.__source = source
+
+    def read(self) -> file_blob:
+        try:
+            with self.__source.open("rb") as handler:
+                return file_blob(handler.read())
+
+        except Exception as error:
+            raise not_readable(self.__source, error)
+            

+ 39 - 0
source/cx_pynstaller/package.py

@@ -0,0 +1,39 @@
+from .file import file
+from .command import command
+from .exceptions import already_packed
+from .package_export import package_export
+
+class package:  
+    def __init__(self, commands: list, files: dict) -> None:
+        self.__commands = tuple(commands)
+        self.__files = tuple([ count for count in files.values() ])
+
+    @property
+    def files(self) -> tuple:
+        return self.__files
+
+    @property
+    def commands(self) -> tuple:
+        return self.__commands
+
+    def export(self) -> package_export:
+        return package_export(self)
+
+class package_builder:
+    def __init__(self) -> None:
+        self.__commands = list()
+        self.__files = dict()
+
+    def add_file(self, target: file) -> object:
+        if target.path_name in self.__files:
+            raise alread_packed(target)
+
+        self.__files[target.path_name] = target
+        return self
+
+    def add_command(self, target: command) -> object:
+        self.__commands.push(target)
+        return self
+
+    def pack(self) -> package:
+        return package(self.__commands, self.__files)

+ 42 - 0
source/cx_pynstaller/package_export.py

@@ -0,0 +1,42 @@
+import json
+
+from .encode import encode
+
+class package_export(encode):
+    def __init__(self, target: object) -> None:
+        self.__target = target
+
+    @property
+    def __commands(self) -> list:
+        result = list()
+
+        for count in self.__target.commands:    
+            result.push(count.encode().encoded_content)
+
+        return result
+
+    @property
+    def __files(self) -> list:
+        result = list()
+
+        for count in self.__target.files:
+            encoded_count = count.encode()
+
+            new_file = dict()
+            new_file["path"] = encoded_count.encoded_path
+            new_file["content"] = encoded_count.encoded_content
+
+            result.push(new_file)
+
+        return result
+
+    @property
+    def __flat_object(self) -> dict:
+        return dict({
+            "commands": self.__commands,
+            "files": self.__files
+        })
+
+    def encode(self) -> str:
+        return self._encode_str(json.dumps(self.__flat_object))
+        

+ 62 - 0
source/cx_pynstaller/package_import.py

@@ -0,0 +1,62 @@
+import json
+
+from .decode import decode
+from .package import package
+from .command import command
+from .command import encoded_command
+from .file import file
+from .file import encoded_file
+from .package import package
+from .package import package_builder
+from .exceptions import broken_package
+
+class package_import(decode):
+    def __init__(self, content: str) -> None:
+        self.__content = content
+
+    @property
+    def __json_string(self) -> str:
+        return self._decode_str(self.__content)
+
+    @property
+    def __flat_content(self) -> dict:
+        return json.loads(self.__json_string)
+
+    def __process_commands(self, commands: list) -> list:
+        result = list()
+
+        for count in commands:
+            result.push(encoded_command(count).decode())
+
+        return result
+
+    def __process_files(self, files: list) -> list:
+        result = list()
+
+        for count in files: 
+            encoded_path = count["path"]
+            encoded_content = count["content"]
+            encoded_count = encoded_file(encoded_path, encoded_content)
+            
+            result.push(encoded_count.decode())
+
+        return result
+
+    def unpack(self) -> package:
+        try:
+            content = self.__flat_content
+            commands = self.__process_commands(content["commands"])
+            files = self.__process_files(content["files"])
+       
+            builder = package_builder()
+            
+            for count in commands:
+                builder.add_command(count)
+
+            for count in files:
+                builder.add_file(count)
+
+            return builder.pack()
+
+        except Exception as error:
+            raise broken_package(error)

+ 1 - 0
source/pynstaller

@@ -0,0 +1 @@
+cx_pynstaller/

+ 12 - 0
tests/000-sample.py

@@ -0,0 +1,12 @@
+import pathlib
+
+current = pathlib.Path(__file__).parent
+root = current.parent
+package = root / pathlib.Path("source")
+
+import sys
+sys.path.append(str(package))
+
+import pynstaller
+
+

+ 20 - 0
tests/001-command.py

@@ -0,0 +1,20 @@
+import pathlib
+
+current = pathlib.Path(__file__).parent
+root = current.parent
+package = root / pathlib.Path("source")
+
+import sys
+sys.path.append(str(package))
+
+import pynstaller
+
+sample = pynstaller.command("echo \"test\"")
+print("Plain: " + sample.content)
+
+encoded = sample.encode()
+print("Encoded: " + encoded.encoded_content)
+
+decoded = encoded.decode()
+print("Decoded: " + decoded.content)
+

+ 28 - 0
tests/002-file.py

@@ -0,0 +1,28 @@
+import pathlib
+
+current = pathlib.Path(__file__).parent
+root = current.parent
+package = root / pathlib.Path("source")
+
+import sys
+sys.path.append(str(package))
+
+import pynstaller
+
+sample_path = pathlib.Path("/etc/resolve.conf")
+sample_content = ("This is sample content").encode("utf-8")
+
+sample_file = pynstaller.file(sample_path, sample_content)
+print("Plain path: " + sample_file.path_name)
+print("Plain content: " + sample_file.content.decode("utf-8"))
+print()
+
+encoded_file = sample_file.encode()
+print("Encoded path: " + encoded_file.encoded_path)
+print("Encoded content: " + encoded_file.encoded_content)
+print()
+
+decoded_file = encoded_file.decode()
+print("Decoded path: " + decoded_file.path_name)
+print("Decoded content: " + decoded_file.content.decode("utf-8"))
+print()

+ 3 - 0
tests/sample.sh

@@ -0,0 +1,3 @@
+#!/bin/bash
+
+echo "This is sample bash script."