Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .alfred.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[alfred]

[alfred.project]
pythonpath_extends = ['tests']
venv = ".venv"
2 changes: 0 additions & 2 deletions .alfred.yml

This file was deleted.

2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:

strategy:
matrix:
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"]
python-version: ["3.8", "3.9", "3.10", "3.11"]

steps:
- uses: actions/checkout@v2
Expand Down
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,8 @@
/dist
/examples/*/build
.idea

**.pyc

/.venv/*
!/.venv/.gitkeep
Empty file added .venv/.gitkeep
Empty file.
6 changes: 3 additions & 3 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"

# pipenv install

[packages]
fixtup = {path = ".", editable=true}
six = "*"

# pipenv install --dev

[dev-packages]
fixtup = {path = ".", extras = ["dev"], editable=true}

# pipenv install --categories="dev_windows"

[dev_windows]
fixtup = {path = ".", extras = ["dev_windows"], editable=true}
528 changes: 272 additions & 256 deletions Pipfile.lock

Large diffs are not rendered by default.

7 changes: 3 additions & 4 deletions alfred/publish.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,7 @@
from click import UsageError, Choice
from plumbum.commands.processes import ProcessExecutionError

import fixtup

ROOT_DIR = os.path.realpath(os.path.join(__file__, "..", ".."))
VERSION = importlib.metadata.version(fixtup.__name__)


@alfred.command("publish", help="tag a new release and trigger pypi publication")
def publish():
Expand All @@ -21,6 +17,9 @@ def publish():

>>> $ alfred publish
"""
import fixtup
VERSION = importlib.metadata.version(fixtup.__name__)

git = alfred.sh("git", "git should be present")
os.chdir(ROOT_DIR)

Expand Down
2 changes: 2 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,15 @@ install_requires =
attrs
click
jinja2
platformdirs
prompt_toolkit
plumbum
pyyaml
python-dotenv
requests
toml


[options.package_data]
fixtup=**/resource/**/*
fixtup_typing=src/fixtup/py.typed
Expand Down
1 change: 0 additions & 1 deletion src/fixtup/cli/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from fixtup.cli.commands.info import info
from fixtup.cli.commands.init import init
from fixtup.cli.commands.new import new
from fixtup.logger import get_logger

BASE_DIR = os.path.realpath(os.path.join(__file__, '..'))

Expand Down
13 changes: 8 additions & 5 deletions src/fixtup/cli/commands/info.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
import click
from click.exceptions import ClickException

from fixtup.context import lib_context, lib_context_setup
from fixtup.exceptions import FixtupException
from fixtup.settings.base import read_settings
from fixtup.settings.base import load_settings


@click.command(help="Display fixtup configuration information")
def info():
try:
settings = read_settings()
click.echo(f"Configuration: {settings.manifest_path}")
click.echo(f"Fixtures: {settings.fixtures_dir}")
lib_context_setup()
load_settings()
fixtup_context = lib_context()
click.echo(f"Configuration: {fixtup_context.manifestpath}")
click.echo(f"Fixtures: {fixtup_context.fixturesdir}")
click.echo(f"Plugins:")
for plugin in settings.plugins:
for plugin in fixtup_context.plugins:
click.echo(f" * {plugin}")

exit(0)
Expand Down
17 changes: 9 additions & 8 deletions src/fixtup/cli/commands/new.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,26 @@
import os

import click

from fixtup.context import lib_context_setup, lib_context
from fixtup.entity.fixture_template import FixtureTemplate
from fixtup.prompt.factory import lookup_prompt
from fixtup.scaffold.base import scaffold_new_fixture
from fixtup.settings import read_settings
from fixtup.settings.base import load_settings


@click.command(help="Scaffold a new fixture")
def new() -> None:
"""
scaffolding command that will generate a new fixture
"""
settings = read_settings()
lib_context_setup()
load_settings()

prompt = lookup_prompt()

fixture_id = prompt.new_fixture(settings.fixtures_dir)
fixtup_context = lib_context()

# output
template = FixtureTemplate.create_from_cli(fixture_id,
settings.fixtures_dir)
fixture_id = prompt.new_fixture(fixtup_context.fixturesdir) # type: ignore

# output
template = FixtureTemplate.create_from_cli(fixture_id, fixtup_context.fixturesdir) # type: ignore
scaffold_new_fixture(template)
66 changes: 66 additions & 0 deletions src/fixtup/context.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
"""
lib_context is a module that manages the global execution context of fixtup. This context is a source of truth shared between all fixtup modules.

It can be retrieved with the ``lib_context()`` function.

>>> from fixtup.context import lib_context
>>> fixtup = lib_context()
"""
from typing import Optional

from fixtup import logger
from fixtup.entity.fixtup import Fixtup

_lib_context: Optional[Fixtup] = None
_fake_lib_context: Optional[Fixtup] = None

def lib_context_setup() -> None:
"""
Initialize the fixtup context.
"""
global _lib_context
if _lib_context is None:
logger.debug('init a global context for fixtup')
if _fake_lib_context is None:
_lib_context = Fixtup()
else:
_lib_context = _fake_lib_context
else:
logger.debug(f'a global context already exist for fixtup, it reuse it')

def lib_context_teardown() -> None:
"""
Uninitialize the fixtup context.
"""
global _lib_context
_lib_context = None


def lib_context() -> Fixtup:
"""
returns the context of the fixtup library
"""
if _lib_context is None:
"""
If you need to emulate fixtup in automatic testing, you should prepare your test with `with context.use_fake_lib_context()`
"""
raise RuntimeError("This code must be executed in fixtup lib context.")

return _lib_context

def lib_context_inject() -> Fixtup:
"""
Inject a fixtup context. This is useful for testing.
"""
global _fake_lib_context
_fake_lib_context = Fixtup()
return _fake_lib_context

def lib_context_eject() -> None:
"""
Eject the injected fixtup context. This is useful for testing.

When tearing down a test, this method cleans up the context that would be loaded when calling `lib_context_setup()`.
"""
global _fake_lib_context
_fake_lib_context = None
52 changes: 52 additions & 0 deletions src/fixtup/entity/fixtup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import typing

import os
import tempfile
from typing import Optional, List

import attr
import platformdirs

if typing.TYPE_CHECKING:
from fixtup.fixture.base import FixtureEngine


class Driver:
mock = 'mock'
prompt_toolkit = 'prompt-toolkit'


@attr.s
class Fixtup:

# Global settings
appname: str = attr.ib(default='fixtup')
appdir: Optional[str] = attr.ib(default=None)
mountdir: Optional[str] = attr.ib(default=None)
pid_owner: Optional[int] = attr.ib(default=None)

driver_prompt: str = Driver.prompt_toolkit
enable_hooks: bool = attr.ib(default=True)
enable_plugins: bool = attr.ib(default=True)

# Each time fixtup.up is invoked, fixtup restarts as if it were a new test run. This mode is necessary to test some workflows in the automatic tests which requires a completely blank fixtup context
emulate_new_process: bool = attr.ib(default=False)

# Project settings
projectloaded: bool = attr.ib(default=False)
projectdir: Optional[str] = attr.ib(default=None)
manifestpath: Optional[str] = attr.ib(default=None)
fixturesdir: Optional[str] = attr.ib(default=None)
plugins: List[str] = attr.ib(factory=list)

# Runtime settings
engine: Optional['FixtureEngine'] = attr.ib(default=None)

def __attrs_post_init__(self):
if self.appdir is None:
self.appdir = platformdirs.user_data_dir(self.appname, self.appname)

if self.mountdir is None:
self.mountdir = tempfile.gettempdir()

self.pid_owner = os.getpid()
3 changes: 1 addition & 2 deletions src/fixtup/entity/fixture_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@

import attr

from fixtup.logger import get_logger
from fixtup import logger

logger = get_logger()

@attr.s
class FixtureTemplate():
Expand Down
8 changes: 4 additions & 4 deletions src/fixtup/entity/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,14 +103,14 @@ def default_settings_for_init(cls, manifest: ProjectManifest, fixture_repository
)

@property
def configuration_dir(self) -> Optional[str]:
def projectdir(self) -> Optional[str]:
if self.manifest is None:
return None

return os.path.dirname(self.manifest.path)

@property
def manifest_path(self) -> Optional[str]:
def manifestpath(self) -> Optional[str]:
if self.manifest is not None:
return self.manifest.path

Expand All @@ -131,8 +131,8 @@ def fixtures_dir(self):

:return: absolute path of the directory that contains the fixtures
"""
if self.configuration_dir is None:
if self.projectdir is None:
return self.fixtures
else:
return os.path.join(self.configuration_dir, self.fixtures)
return os.path.join(self.projectdir, self.fixtures)

Loading